- Added the new mail system. Requires optimization and tests.
- Updated the maildb sql structure. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11548 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
0e39094a11
commit
c34325a53b
@ -6,6 +6,9 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
||||
2007/10/22
|
||||
* Heat isn't supposed to consume SP when used against players [Playtester]
|
||||
- please report if it still consumes SP in pvp
|
||||
* Added the new mail system implementation (Requires more test and
|
||||
optimizations) [Zephyrus]
|
||||
- Updated the mail DB structure.
|
||||
2007/10/21
|
||||
* Fixed a small mistake in r11503 causing a fatal error&exit on unix
|
||||
when you try to do a graceful exit (by ctrl+c for example) [ultramage]
|
||||
|
@ -754,17 +754,17 @@ packet_ver: 18
|
||||
0x0190,21,actionrequest,5:20
|
||||
0x0216,6
|
||||
//Start mail system?
|
||||
0x023f,2
|
||||
0x023f,2,mailrefresh,0
|
||||
0x0240,8
|
||||
0x0241,6
|
||||
0x0241,6,mailread,2
|
||||
0x0242,-1
|
||||
0x0243,6
|
||||
0x0244,6
|
||||
0x0243,6,maildelete,2
|
||||
0x0244,6,mailgetattach,2
|
||||
0x0245,7
|
||||
//Start writing a mail?
|
||||
0x0246,4
|
||||
0x0246,4,mailwinopen,2
|
||||
//Send Item/Zeny
|
||||
0x0247,8
|
||||
0x0247,8,mailsetattach,2:4
|
||||
//Message
|
||||
0x0248,68
|
||||
//Delivered?
|
||||
@ -811,7 +811,7 @@ packet_ver: 19
|
||||
|
||||
//2005-08-29aSakexe
|
||||
0x0240,-1
|
||||
0x0248,-1
|
||||
0x0248,-1,mailsend,2:4:28:68
|
||||
0x0255,5
|
||||
0x0256,0
|
||||
0x0257,8
|
||||
@ -871,7 +871,7 @@ packet_ver: 19
|
||||
0x0274,8
|
||||
|
||||
//2006-03-13aSakexe
|
||||
0x0273,30
|
||||
0x0273,30,mailreturn,2:6
|
||||
|
||||
//2006-03-27aSakexe
|
||||
packet_ver: 20
|
||||
|
@ -1,12 +1,23 @@
|
||||
DROP TABLE IF EXISTS `mail`;
|
||||
CREATE TABLE `mail` (
|
||||
`message_id` int(11) NOT NULL auto_increment,
|
||||
`to_account_id` int(11) NOT NULL default '0',
|
||||
`to_char_name` varchar(24) NOT NULL default '',
|
||||
`from_account_id` int(11) NOT NULL default '0',
|
||||
`from_char_name` varchar(24) NOT NULL default '',
|
||||
`message` varchar(80) NOT NULL default '',
|
||||
`read_flag` tinyint(1) NOT NULL default '0',
|
||||
`priority` tinyint(1) NOT NULL default '0',
|
||||
`check_flag` tinyint(1) NOT NULL default '0',
|
||||
PRIMARY KEY (`message_id`)
|
||||
) TYPE=MyISAM;
|
||||
`id` bigint(20) unsigned NOT NULL auto_increment,
|
||||
`send_name` tinytext NOT NULL DEFAULT '',
|
||||
`send_id` int(11) unsigned NOT NULL default '0',
|
||||
`dest_name` tinytext NOT NULL DEFAULT '',
|
||||
`dest_id` int(11) unsigned NOT NULL default '0',
|
||||
`title` tinytext NOT NULL DEFAULT '',
|
||||
`message` text NOT NULL DEFAULT '',
|
||||
`time` int(11) unsigned NOT NULL default '0',
|
||||
`read_flag` tinyint(1) unsigned NOT NULL default '0',
|
||||
`zeny` int(11) unsigned NOT NULL default '0',
|
||||
`nameid` int(11) unsigned NOT NULL default '0',
|
||||
`amount` int(11) unsigned NOT NULL default '0',
|
||||
`refine` tinyint(3) unsigned NOT NULL default '0',
|
||||
`attribute` tinyint(4) unsigned NOT NULL default '0',
|
||||
`identify` smallint(6) NOT NULL default '0',
|
||||
`card0` smallint(11) NOT NULL default '0',
|
||||
`card1` smallint(11) NOT NULL default '0',
|
||||
`card2` smallint(11) NOT NULL default '0',
|
||||
`card3` smallint(11) NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM;
|
||||
|
@ -9,7 +9,7 @@ COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h
|
||||
../common/strlib.h ../common/grfio.h \
|
||||
../common/mapindex.h ../common/ers.h ../common/sql.h
|
||||
|
||||
CHAR_OBJ = char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o
|
||||
CHAR_OBJ = char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o int_mail.o
|
||||
|
||||
HAVE_MYSQL=@HAVE_MYSQL@
|
||||
ifeq ($(HAVE_MYSQL),yes)
|
||||
@ -54,3 +54,4 @@ int_guild.o: int_guild.c int_guild.h inter.h $(COMMON_H)
|
||||
int_storage.o: int_storage.c int_storage.h char.h $(COMMON_H)
|
||||
int_pet.o: int_pet.c int_pet.h inter.h char.h $(COMMON_H)
|
||||
int_homun.o: int_homun.c int_homun.h inter.h char.h $(COMMON_H)
|
||||
int_mail.o: int_mail.c int_mail.h inter.h char.h $(COMMON_H)
|
@ -59,6 +59,7 @@ char guild_skill_db[256] = "guild_skill";
|
||||
char guild_storage_db[256] = "guild_storage";
|
||||
char party_db[256] = "party";
|
||||
char pet_db[256] = "pet";
|
||||
char mail_db[256] = "mail"; // MAIL SYSTEM
|
||||
char friend_db[256] = "friends";
|
||||
char hotkey_db[256] = "hotkey";
|
||||
|
||||
@ -3447,6 +3448,8 @@ void sql_config_read(const char* cfgName)
|
||||
strcpy(party_db,w2);
|
||||
else if(!strcmpi(w1,"pet_db"))
|
||||
strcpy(pet_db,w2);
|
||||
else if(!strcmpi(w1,"mail_db"))
|
||||
strcpy(mail_db,w2);
|
||||
else if(!strcmpi(w1,"friend_db"))
|
||||
strcpy(friend_db,w2);
|
||||
else if(!strcmpi(w1,"hotkey_db"))
|
||||
|
@ -57,6 +57,7 @@ extern char guild_skill_db[256];
|
||||
extern char guild_storage_db[256];
|
||||
extern char party_db[256];
|
||||
extern char pet_db[256];
|
||||
extern char mail_db[256];
|
||||
|
||||
extern int db_use_sqldbs; // added for sql item_db read for char server [Valaris]
|
||||
|
||||
|
476
src/char_sql/int_mail.c
Normal file
476
src/char_sql/int_mail.c
Normal file
@ -0,0 +1,476 @@
|
||||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
|
||||
#include "../common/mmo.h"
|
||||
#include "../common/malloc.h"
|
||||
#include "../common/showmsg.h"
|
||||
#include "../common/socket.h"
|
||||
#include "../common/strlib.h"
|
||||
#include "../common/sql.h"
|
||||
#include "char.h"
|
||||
#include "inter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct mail_data *mail_data_pt = NULL;
|
||||
|
||||
time_t calc_times(void)
|
||||
{
|
||||
time_t temp = time(NULL);
|
||||
return mktime(localtime(&temp));
|
||||
}
|
||||
|
||||
int mail_fromsql(int char_id, struct mail_data *md)
|
||||
{
|
||||
int i, j;
|
||||
struct mail_message *msg;
|
||||
struct item *item;
|
||||
char *data;
|
||||
StringBuf buf;
|
||||
|
||||
memset(md, 0, sizeof(struct mail_data));
|
||||
md->amount = 0;
|
||||
md->satured = 0;
|
||||
|
||||
StringBuf_Init(&buf);
|
||||
StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`read_flag`,"
|
||||
"`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, MAX_MAIL_INBOX + 1);
|
||||
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, StringBuf_Value(&buf)) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
|
||||
StringBuf_Destroy(&buf);
|
||||
|
||||
for (i = 0; i < MAX_MAIL_INBOX && SQL_SUCCESS == Sql_NextRow(mail_handle); ++i )
|
||||
{
|
||||
msg = &md->msg[i];
|
||||
Sql_GetData(mail_handle, 0, &data, NULL); msg->id = atoi(data);
|
||||
Sql_GetData(mail_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH);
|
||||
Sql_GetData(mail_handle, 2, &data, NULL); msg->send_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH);
|
||||
Sql_GetData(mail_handle, 4, &data, NULL); msg->dest_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH);
|
||||
Sql_GetData(mail_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH);
|
||||
Sql_GetData(mail_handle, 7, &data, NULL); msg->timestamp = atoi(data);
|
||||
Sql_GetData(mail_handle, 8, &data, NULL); msg->read = atoi(data);
|
||||
Sql_GetData(mail_handle, 9, &data, NULL); msg->zeny = atoi(data);
|
||||
item = &msg->item;
|
||||
Sql_GetData(mail_handle,10, &data, NULL); item->amount = (short)atoi(data);
|
||||
Sql_GetData(mail_handle,11, &data, NULL); item->nameid = atoi(data);
|
||||
Sql_GetData(mail_handle,12, &data, NULL); item->refine = atoi(data);
|
||||
Sql_GetData(mail_handle,13, &data, NULL); item->attribute = atoi(data);
|
||||
Sql_GetData(mail_handle,14, &data, NULL); item->identify = atoi(data);
|
||||
|
||||
for (j = 0; j < MAX_SLOTS; j++)
|
||||
{
|
||||
Sql_GetData(mail_handle, 15 + j, &data, NULL);
|
||||
item->card[j] = atoi(data);
|
||||
}
|
||||
}
|
||||
|
||||
if ( SQL_SUCCESS == Sql_NextRow(mail_handle) )
|
||||
md->satured = 1; // New Mails cannot arrive
|
||||
else
|
||||
md->satured = 0;
|
||||
|
||||
md->amount = i;
|
||||
md->changed = 0;
|
||||
Sql_FreeResult(mail_handle);
|
||||
|
||||
md->unchecked = 0;
|
||||
md->unreaded = 0;
|
||||
for (i = 0; i < md->amount; i++)
|
||||
{
|
||||
msg = &md->msg[i];
|
||||
if (!msg->read)
|
||||
{
|
||||
if ( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `read_flag` = '1' WHERE `id` = '%d'", mail_db, msg->id) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
|
||||
md->unchecked++;
|
||||
}
|
||||
else if ( msg->read == 1 )
|
||||
md->unreaded++;
|
||||
|
||||
msg->read = (msg->read < 2)?0:1;
|
||||
}
|
||||
|
||||
ShowInfo("mail load complete from DB - id: %d (total: %d)\n", char_id, md->amount);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mail_savemessage(struct mail_message *msg)
|
||||
{
|
||||
StringBuf buf;
|
||||
int j;
|
||||
char esc_send_name[NAME_LENGTH*2+1], esc_dest_name[NAME_LENGTH*2+1];
|
||||
char esc_title[MAIL_TITLE_LENGTH*2+1], esc_body[MAIL_BODY_LENGTH*2+1];
|
||||
|
||||
if (!msg)
|
||||
return 0;
|
||||
|
||||
Sql_EscapeStringLen(mail_handle, esc_send_name, msg->send_name, strnlen(msg->send_name, NAME_LENGTH));
|
||||
Sql_EscapeStringLen(mail_handle, esc_dest_name, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH));
|
||||
Sql_EscapeStringLen(mail_handle, esc_title, msg->title, strnlen(msg->title, MAIL_TITLE_LENGTH));
|
||||
Sql_EscapeStringLen(mail_handle, esc_body, msg->body, strnlen(msg->body, MAIL_BODY_LENGTH));
|
||||
|
||||
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);
|
||||
for (j = 0; j < MAX_SLOTS; j++)
|
||||
StringBuf_Printf(&buf, ", `card%d`", j);
|
||||
StringBuf_Printf(&buf, ") VALUES ('%s', '%d', '%s', '%d', '%s', '%s', '%d', '0', '%d', '%d', '%d', '%d', '%d', '%d'",
|
||||
esc_send_name, msg->send_id, esc_dest_name, msg->dest_id, esc_title, esc_body, msg->timestamp, 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, ")");
|
||||
|
||||
if( SQL_ERROR == Sql_QueryStr(mail_handle, StringBuf_Value(&buf)) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
j = (int)Sql_LastInsertId(mail_handle);
|
||||
|
||||
StringBuf_Destroy(&buf);
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
int mail_loadmessage(int char_id, int mail_id, struct mail_message *message, short flag)
|
||||
{
|
||||
char *data;
|
||||
struct item *item;
|
||||
int j = 0;
|
||||
StringBuf buf;
|
||||
|
||||
StringBuf_Init(&buf);
|
||||
StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`read_flag`,"
|
||||
"`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);
|
||||
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, StringBuf_Value(&buf)) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
else if( Sql_NumRows(mail_handle) == 0 )
|
||||
ShowWarning("Char %d trying to read an invalid mail.\n", char_id);
|
||||
else
|
||||
{
|
||||
Sql_NextRow(mail_handle);
|
||||
|
||||
Sql_GetData(mail_handle, 0, &data, NULL); message->id = atoi(data);
|
||||
Sql_GetData(mail_handle, 1, &data, NULL); safestrncpy(message->send_name, data, NAME_LENGTH);
|
||||
Sql_GetData(mail_handle, 2, &data, NULL); message->send_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 3, &data, NULL); safestrncpy(message->dest_name, data, NAME_LENGTH);
|
||||
Sql_GetData(mail_handle, 4, &data, NULL); message->dest_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 5, &data, NULL); safestrncpy(message->title, data, MAIL_TITLE_LENGTH);
|
||||
Sql_GetData(mail_handle, 6, &data, NULL); safestrncpy(message->body, data, MAIL_BODY_LENGTH);
|
||||
Sql_GetData(mail_handle, 7, &data, NULL); message->timestamp = atoi(data);
|
||||
Sql_GetData(mail_handle, 8, &data, NULL); message->read = atoi(data);
|
||||
Sql_GetData(mail_handle, 9, &data, NULL); message->zeny = atoi(data);
|
||||
item = &message->item;
|
||||
Sql_GetData(mail_handle,10, &data, NULL); item->amount = (short)atoi(data);
|
||||
Sql_GetData(mail_handle,11, &data, NULL); item->nameid = atoi(data);
|
||||
Sql_GetData(mail_handle,12, &data, NULL); item->refine = atoi(data);
|
||||
Sql_GetData(mail_handle,13, &data, NULL); item->attribute = atoi(data);
|
||||
Sql_GetData(mail_handle,14, &data, NULL); item->identify = atoi(data);
|
||||
for (j = 0; j < MAX_SLOTS; j++)
|
||||
{
|
||||
Sql_GetData(mail_handle,15 + j, &data, NULL);
|
||||
item->card[j] = atoi(data);
|
||||
}
|
||||
|
||||
j = 1;
|
||||
}
|
||||
|
||||
StringBuf_Destroy(&buf);
|
||||
Sql_FreeResult(mail_handle);
|
||||
|
||||
if (message->read == 1)
|
||||
{
|
||||
message->read = 0;
|
||||
if (flag)
|
||||
if ( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `read_flag` = '2' WHERE `id` = '%d'", mail_db, message->id) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
}
|
||||
else
|
||||
message->read = 1;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Client Inbox Request
|
||||
*------------------------------------------*/
|
||||
int mapif_Mail_sendinbox(int fd, int char_id, unsigned char flag)
|
||||
{
|
||||
WFIFOHEAD(fd, sizeof(struct mail_data) + 9);
|
||||
mail_fromsql(char_id, mail_data_pt);
|
||||
WFIFOW(fd,0) = 0x3848;
|
||||
WFIFOW(fd,2) = sizeof(struct mail_data) + 9;
|
||||
WFIFOL(fd,4) = char_id;
|
||||
WFIFOB(fd,8) = flag;
|
||||
memcpy(WFIFOP(fd,9),mail_data_pt,sizeof(struct mail_data));
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mapif_parse_Mail_requestinbox(int fd)
|
||||
{
|
||||
RFIFOHEAD(fd);
|
||||
mapif_Mail_sendinbox(fd, RFIFOL(fd,2), RFIFOB(fd,6));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Mail Readed Mark
|
||||
*------------------------------------------*/
|
||||
int mapif_parse_Mail_read(int fd)
|
||||
{
|
||||
int mail_id;
|
||||
RFIFOHEAD(fd);
|
||||
|
||||
mail_id = RFIFOL(fd,2);
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `read_flag` = '2' WHERE `id` = '%d'", mail_db, mail_id) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Client Attachment Request
|
||||
*------------------------------------------*/
|
||||
int mail_DeleteAttach(int mail_id)
|
||||
{
|
||||
StringBuf buf;
|
||||
int i;
|
||||
|
||||
StringBuf_Init(&buf);
|
||||
StringBuf_Printf(&buf, "UPDATE `%s` SET `zeny` = '0', `nameid` = '0', `amount` = '0', `refine` = '0', `attribute` = '0', `identify` = '0'", mail_db);
|
||||
for (i = 0; i < MAX_SLOTS; i++)
|
||||
StringBuf_Printf(&buf, ", `card%d` = '0'", i);
|
||||
StringBuf_Printf(&buf, " WHERE `id` = '%d'", mail_id);
|
||||
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, StringBuf_Value(&buf)) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
StringBuf_Destroy(&buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
StringBuf_Destroy(&buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mapif_Mail_getattach(int fd, int char_id, int mail_id)
|
||||
{
|
||||
struct mail_message *message = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
|
||||
|
||||
if( mail_loadmessage(char_id, mail_id, message, 0) )
|
||||
{
|
||||
if( (message->item.nameid < 1 || message->item.amount < 1) && message->zeny < 1 )
|
||||
{
|
||||
aFree(message);
|
||||
return 0; // No Attachment
|
||||
}
|
||||
|
||||
if( mail_DeleteAttach(mail_id) )
|
||||
{
|
||||
WFIFOHEAD(fd, sizeof(struct item) + 12);
|
||||
WFIFOW(fd,0) = 0x384a;
|
||||
WFIFOW(fd,2) = sizeof(struct item) + 12;
|
||||
WFIFOL(fd,4) = char_id;
|
||||
WFIFOL(fd,8) = (message->zeny > 0)?message->zeny:0;
|
||||
memcpy(WFIFOP(fd,12), &message->item, sizeof(struct item));
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
}
|
||||
}
|
||||
|
||||
aFree(message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mapif_parse_Mail_getattach(int fd)
|
||||
{
|
||||
RFIFOHEAD(fd);
|
||||
mapif_Mail_getattach(fd, RFIFOL(fd,2), RFIFOL(fd,6));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Delete Mail
|
||||
*------------------------------------------*/
|
||||
int mapif_Mail_delete(int fd, int char_id, int mail_id)
|
||||
{
|
||||
short flag = 0;
|
||||
|
||||
if ( SQL_ERROR == Sql_Query(mail_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
flag = 1;
|
||||
}
|
||||
|
||||
WFIFOHEAD(fd,11);
|
||||
WFIFOW(fd,0) = 0x384b;
|
||||
WFIFOL(fd,2) = char_id;
|
||||
WFIFOL(fd,6) = mail_id;
|
||||
WFIFOW(fd,10) = flag;
|
||||
WFIFOSET(fd,12);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mapif_parse_Mail_delete(int fd)
|
||||
{
|
||||
RFIFOHEAD(fd);
|
||||
mapif_Mail_delete(fd, RFIFOL(fd,2), RFIFOL(fd,6));
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
* Return Mail
|
||||
*------------------------------------------*/
|
||||
int mapif_Mail_return(int fd, int char_id, int mail_id)
|
||||
{
|
||||
struct mail_message *msg = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
|
||||
int new_mail = 0;
|
||||
|
||||
if( mail_loadmessage(char_id, mail_id, msg, 0) )
|
||||
{
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
else
|
||||
{
|
||||
char temp_[MAIL_TITLE_LENGTH];
|
||||
|
||||
swap(msg->send_id, msg->dest_id);
|
||||
safestrncpy(temp_, msg->send_name, NAME_LENGTH);
|
||||
safestrncpy(msg->send_name, msg->dest_name, NAME_LENGTH);
|
||||
safestrncpy(msg->dest_name, temp_, NAME_LENGTH);
|
||||
|
||||
snprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg->title);
|
||||
safestrncpy(msg->title, temp_, MAIL_TITLE_LENGTH);
|
||||
msg->timestamp = (unsigned int)calc_times();
|
||||
|
||||
new_mail = mail_savemessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
aFree(msg);
|
||||
|
||||
WFIFOHEAD(fd,14);
|
||||
WFIFOW(fd,0) = 0x384c;
|
||||
WFIFOL(fd,2) = char_id;
|
||||
WFIFOL(fd,6) = mail_id;
|
||||
WFIFOL(fd,10) = new_mail;
|
||||
WFIFOSET(fd,14);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mapif_parse_Mail_return(int fd)
|
||||
{
|
||||
RFIFOHEAD(fd);
|
||||
mapif_Mail_return(fd, RFIFOL(fd,2), RFIFOL(fd,6));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mapif_Mail_send(int fd, struct mail_message *msg)
|
||||
{
|
||||
int len = strlen(msg->title) + 16;
|
||||
|
||||
WFIFOHEAD(fd,len);
|
||||
WFIFOW(fd,0) = 0x384d;
|
||||
WFIFOW(fd,2) = len;
|
||||
WFIFOL(fd,4) = msg->send_id;
|
||||
WFIFOL(fd,8) = msg->id;
|
||||
WFIFOL(fd,12) = msg->dest_id;
|
||||
memcpy(WFIFOP(fd,16), msg->title, strlen(msg->title));
|
||||
WFIFOSET(fd,len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mapif_parse_Mail_send(int fd)
|
||||
{
|
||||
struct mail_message *msg;
|
||||
int mail_id = 0, account_id = 0;
|
||||
|
||||
if(RFIFOW(fd,2) != 8 + sizeof(struct mail_message))
|
||||
return 0;
|
||||
|
||||
msg = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
|
||||
memcpy(msg, RFIFOP(fd,8), sizeof(struct mail_message));
|
||||
|
||||
account_id = RFIFOL(fd,4);
|
||||
|
||||
if( !msg->dest_id )
|
||||
{
|
||||
// Try to find the Dest Char by Name
|
||||
char esc_name[NAME_LENGTH*2+1];
|
||||
|
||||
Sql_EscapeStringLen(sql_handle, esc_name, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH));
|
||||
if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
|
||||
Sql_ShowDebug(sql_handle);
|
||||
else if ( Sql_NumRows(sql_handle) > 0 )
|
||||
{
|
||||
char *data;
|
||||
Sql_NextRow(sql_handle);
|
||||
Sql_GetData(sql_handle, 0, &data, NULL);
|
||||
if (atoi(data) != account_id)
|
||||
{ // Cannot sends mail to char in the same account
|
||||
Sql_GetData(sql_handle, 1, &data, NULL);
|
||||
msg->dest_id = atoi(data);
|
||||
}
|
||||
}
|
||||
Sql_FreeResult(sql_handle);
|
||||
}
|
||||
|
||||
if( msg->dest_id > 0 )
|
||||
mail_id = mail_savemessage(msg);
|
||||
|
||||
msg->id = mail_id;
|
||||
mapif_Mail_send(fd, msg);
|
||||
|
||||
aFree(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Packets From Map Server
|
||||
*------------------------------------------*/
|
||||
int inter_mail_parse_frommap(int fd)
|
||||
{
|
||||
switch(RFIFOW(fd,0))
|
||||
{
|
||||
case 0x3048: mapif_parse_Mail_requestinbox(fd); break;
|
||||
case 0x3049: mapif_parse_Mail_read(fd); break;
|
||||
case 0x304a: mapif_parse_Mail_getattach(fd); break;
|
||||
case 0x304b: mapif_parse_Mail_delete(fd); break;
|
||||
case 0x304c: mapif_parse_Mail_return(fd); break;
|
||||
case 0x304d: mapif_parse_Mail_send(fd); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int inter_mail_sql_init(void)
|
||||
{
|
||||
mail_data_pt = (struct mail_data*)aCalloc(sizeof(struct mail_data), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void inter_mail_sql_final(void)
|
||||
{
|
||||
if (mail_data_pt) aFree(mail_data_pt);
|
||||
return;
|
||||
}
|
12
src/char_sql/int_mail.h
Normal file
12
src/char_sql/int_mail.h
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
|
||||
#ifndef _INT_MAIL_SQL_H_
|
||||
#define _INT_MAIL_SQL_H_
|
||||
|
||||
int inter_mail_parse_frommap(int fd);
|
||||
|
||||
int inter_mail_sql_init(void);
|
||||
void inter_mail_sql_final(void);
|
||||
|
||||
#endif /* _INT_MAIL_SQL_H_ */
|
@ -15,6 +15,7 @@
|
||||
#include "int_storage.h"
|
||||
#include "int_pet.h"
|
||||
#include "int_homun.h"
|
||||
#include "int_mail.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -26,6 +27,7 @@
|
||||
|
||||
Sql* sql_handle = NULL;
|
||||
Sql* lsql_handle = NULL;
|
||||
Sql* mail_handle = NULL;
|
||||
|
||||
int char_server_port = 3306;
|
||||
char char_server_ip[32] = "127.0.0.1";
|
||||
@ -40,6 +42,12 @@ char login_server_id[32] = "ragnarok";
|
||||
char login_server_pw[32] = "ragnarok";
|
||||
char login_server_db[32] = "ragnarok";
|
||||
|
||||
int mail_server_port = 3306;
|
||||
char mail_server_ip[32] = "127.0.0.1";
|
||||
char mail_server_id[32] = "ragnarok";
|
||||
char mail_server_pw[32] = "ragnarok";
|
||||
char mail_server_db[32] = "ragnarok";
|
||||
|
||||
#ifndef TXT_SQL_CONVERT
|
||||
|
||||
static struct accreg *accreg_pt;
|
||||
@ -53,7 +61,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, 0, 0, 0, 0, 0, 0, 0, 0, // 3840-
|
||||
9, 9,-1, 0, 0, 0, 0, 0, -1, 0,-1,12, 14,-1, 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-
|
||||
@ -65,7 +73,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, 0, 0, 0, 0, 0, 0, 0, 0, // 3040-
|
||||
5, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 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-
|
||||
@ -270,6 +278,28 @@ static int inter_config_read(const char* cfgName)
|
||||
strcpy(login_server_db, w2);
|
||||
ShowStatus ("set login_server_db : %s\n", w2);
|
||||
}
|
||||
// MAIL SYSTEM
|
||||
else
|
||||
if(!strcmpi(w1,"mail_server_ip")) {
|
||||
strcpy(mail_server_ip, w2);
|
||||
ShowStatus ("set mail_server_ip : %s\n", w2);
|
||||
} else
|
||||
if(!strcmpi(w1,"mail_server_port")) {
|
||||
mail_server_port = atoi(w2);
|
||||
ShowStatus ("set mail_server_port : %s\n", w2);
|
||||
} else
|
||||
if(!strcmpi(w1,"mail_server_id")) {
|
||||
strcpy(mail_server_id, w2);
|
||||
ShowStatus ("set mail_server_id : %s\n", w2);
|
||||
} else
|
||||
if(!strcmpi(w1,"mail_server_pw")) {
|
||||
strcpy(mail_server_pw, w2);
|
||||
ShowStatus ("set mail_server_pw : %s\n", w2);
|
||||
} else
|
||||
if(!strcmpi(w1,"mail_server_db")) {
|
||||
strcpy(mail_server_db, w2);
|
||||
ShowStatus ("set mail_server_db : %s\n", w2);
|
||||
}
|
||||
#ifndef TXT_SQL_CONVERT
|
||||
else if(!strcmpi(w1,"party_share_level"))
|
||||
party_share_level = atoi(w2);
|
||||
@ -314,6 +344,7 @@ int inter_sql_ping(int tid, unsigned int tick, int id, int data)
|
||||
{
|
||||
ShowInfo("Pinging SQL server to keep connection alive...\n");
|
||||
Sql_Ping(sql_handle);
|
||||
Sql_Ping(mail_handle);
|
||||
if( char_gm_read )
|
||||
Sql_Ping(lsql_handle);
|
||||
return 0;
|
||||
@ -358,6 +389,16 @@ int inter_init_sql(const char *file)
|
||||
Sql_Free(sql_handle);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// MAIL SYSTEM
|
||||
mail_handle = Sql_Malloc();
|
||||
ShowInfo("Connect Mail DB server.... (Character Server)\n");
|
||||
if ( SQL_ERROR == Sql_Connect(mail_handle, mail_server_id, mail_server_pw, mail_server_ip, (uint16)mail_server_port, mail_server_db) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
Sql_Free(mail_handle);
|
||||
Sql_Free(sql_handle);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#ifndef TXT_SQL_CONVERT
|
||||
else if (inter_sql_test()) {
|
||||
ShowStatus("Connect Success! (Character Server)\n");
|
||||
@ -370,6 +411,7 @@ int inter_init_sql(const char *file)
|
||||
{
|
||||
Sql_ShowDebug(lsql_handle);
|
||||
Sql_Free(lsql_handle);
|
||||
Sql_Free(mail_handle);
|
||||
Sql_Free(sql_handle);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -396,6 +438,7 @@ int inter_init_sql(const char *file)
|
||||
inter_pet_sql_init();
|
||||
inter_homunculus_sql_init(); // albator
|
||||
inter_accreg_sql_init();
|
||||
inter_mail_sql_init();
|
||||
|
||||
sql_ping_init();
|
||||
#endif //TXT_SQL_CONVERT
|
||||
@ -429,6 +472,7 @@ int inter_sql_test (void)
|
||||
ShowSQL ("Field `%s` not be found in `%s`. Consider updating your database!\n", fields[i], char_db);
|
||||
if( lsql_handle )
|
||||
Sql_Free(lsql_handle);
|
||||
Sql_Free(mail_handle);
|
||||
Sql_Free(sql_handle);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -863,6 +907,7 @@ int inter_parse_frommap(int fd)
|
||||
|| inter_storage_parse_frommap(fd)
|
||||
|| inter_pet_parse_frommap(fd)
|
||||
|| inter_homunculus_parse_frommap(fd)
|
||||
|| inter_mail_parse_frommap(fd)
|
||||
)
|
||||
break;
|
||||
else
|
||||
|
@ -26,6 +26,7 @@ extern char inter_log_filename[1024];
|
||||
|
||||
extern Sql* sql_handle;
|
||||
extern Sql* lsql_handle;
|
||||
extern Sql* mail_handle;
|
||||
|
||||
extern int char_server_port;
|
||||
extern char char_server_ip[32];
|
||||
@ -39,6 +40,12 @@ extern char login_db_server_id[32];
|
||||
extern char login_db_server_pw[32];
|
||||
extern char login_db_server_db[32];
|
||||
|
||||
extern int mail_server_port;
|
||||
extern char mail_server_ip[32];
|
||||
extern char mail_server_id[32];
|
||||
extern char mail_server_pw[32];
|
||||
extern char mail_server_db[32];
|
||||
|
||||
extern char main_chat_nick[16];
|
||||
|
||||
int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type);
|
||||
|
@ -105,6 +105,11 @@
|
||||
#define HM_CLASS_BASE 6001
|
||||
#define HM_CLASS_MAX (HM_CLASS_BASE+MAX_HOMUNCULUS_CLASS-1)
|
||||
|
||||
//Mail System
|
||||
#define MAX_MAIL_INBOX 30
|
||||
#define MAIL_TITLE_LENGTH 40
|
||||
#define MAIL_BODY_LENGTH 200
|
||||
|
||||
struct item {
|
||||
int id;
|
||||
short nameid;
|
||||
@ -236,6 +241,32 @@ struct mmo_charstatus {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct mail_message {
|
||||
unsigned int id;
|
||||
int send_id;
|
||||
char send_name[NAME_LENGTH];
|
||||
int dest_id;
|
||||
char dest_name[NAME_LENGTH];
|
||||
|
||||
char title[MAIL_TITLE_LENGTH];
|
||||
char body[MAIL_BODY_LENGTH];
|
||||
|
||||
unsigned char read;
|
||||
unsigned int timestamp;
|
||||
|
||||
int zeny;
|
||||
struct item item;
|
||||
};
|
||||
|
||||
struct mail_data {
|
||||
short amount;
|
||||
short changed;
|
||||
short satured;
|
||||
struct mail_message msg[MAX_MAIL_INBOX];
|
||||
|
||||
short unchecked, unreaded;
|
||||
};
|
||||
|
||||
struct registry {
|
||||
int global_num;
|
||||
struct global_reg global[GLOBAL_REG_NUM];
|
||||
|
@ -270,13 +270,7 @@ ACMD_FUNC(homshuffle); //[Skotlex]
|
||||
ACMD_FUNC(showmobs); //KarLaeda
|
||||
ACMD_FUNC(feelreset); //[HiddenDragon]
|
||||
#ifndef TXT_ONLY
|
||||
ACMD_FUNC(checkmail); // [Valaris]
|
||||
ACMD_FUNC(listmail); // [Valaris]
|
||||
ACMD_FUNC(listnewmail); // [Valaris]
|
||||
ACMD_FUNC(readmail); // [Valaris]
|
||||
ACMD_FUNC(deletemail); // [Valaris]
|
||||
ACMD_FUNC(sendmail); // [Valaris]
|
||||
ACMD_FUNC(sendprioritymail); // [Valaris]
|
||||
ACMD_FUNC(mail); // [MAIL SYSTEM]
|
||||
ACMD_FUNC(refreshonline); // [Valaris]
|
||||
#endif
|
||||
#ifdef DMALLOC
|
||||
@ -574,13 +568,7 @@ static AtCommandInfo atcommand_info[] = {
|
||||
{ AtCommand_ShowMobs, "@showmobs", 10, atcommand_showmobs }, //KarLaeda
|
||||
{ AtCommand_FeelReset, "@feelreset", 10, atcommand_feelreset }, //[HiddenDragon]
|
||||
#ifndef TXT_ONLY // sql-only commands
|
||||
{ AtCommand_CheckMail, "@checkmail", 1, atcommand_listmail }, // [Valaris]
|
||||
{ AtCommand_ListMail, "@listmail", 1, atcommand_listmail }, // [Valaris]
|
||||
{ AtCommand_ListNewMail, "@listnewmail", 1, atcommand_listmail }, // [Valaris]
|
||||
{ AtCommand_ReadMail, "@readmail", 1, atcommand_readmail }, // [Valaris]
|
||||
{ AtCommand_DeleteMail, "@deletemail", 1, atcommand_deletemail }, // [Valaris]
|
||||
{ AtCommand_SendMail, "@sendmail", 1, atcommand_sendmail }, // [Valaris]
|
||||
{ AtCommand_SendPriorityMail, "@sendprioritymail",80, atcommand_sendmail }, // [Valaris]
|
||||
{ AtCommand_Mail, "@mail", 1, atcommand_mail }, // [Mail System]
|
||||
{ AtCommand_RefreshOnline, "@refreshonline", 99, atcommand_refreshonline }, // [Valaris]
|
||||
#endif
|
||||
#ifdef DMALLOC
|
||||
@ -7893,97 +7881,13 @@ int atcommand_killid2(const int fd, struct map_session_data* sd, const char* com
|
||||
#ifndef TXT_ONLY /* Begin SQL-Only commands */
|
||||
|
||||
/*==========================================
|
||||
* Mail System commands by [Valaris]
|
||||
* MAIL SYSTEM
|
||||
*------------------------------------------*/
|
||||
int atcommand_listmail(const int fd, struct map_session_data* sd, const char* command, const char* message)
|
||||
int atcommand_mail(const int fd, struct map_session_data* sd, const char* command, const char* message)
|
||||
{
|
||||
if(!mail_server_enable)
|
||||
return 0;
|
||||
|
||||
nullpo_retr(-1, sd);
|
||||
|
||||
if(strlen(command)==12) // @listnewmail
|
||||
mail_check(sd,3);
|
||||
else if(strlen(command)==9) // @listmail
|
||||
mail_check(sd,2);
|
||||
else // @checkmail
|
||||
mail_check(sd,1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atcommand_readmail(const int fd, struct map_session_data* sd, const char* command, const char* message)
|
||||
{
|
||||
int index;
|
||||
if(!mail_server_enable)
|
||||
return 0;
|
||||
|
||||
nullpo_retr(-1, sd);
|
||||
|
||||
if (!message || !*message) {
|
||||
clif_displaymessage(sd->fd,"You must specify a message number.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
index = atoi(message);
|
||||
if (index < 1) {
|
||||
clif_displaymessage(sd->fd,"Message number cannot be negative or zero.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mail_read(sd,index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atcommand_deletemail(const int fd, struct map_session_data* sd, const char* command, const char* message)
|
||||
{
|
||||
int index;
|
||||
if(!mail_server_enable)
|
||||
return 0;
|
||||
|
||||
nullpo_retr(-1, sd);
|
||||
|
||||
if (!message || !*message) {
|
||||
clif_displaymessage(sd->fd,"You must specify a message number.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
index = atoi(message);
|
||||
if (index < 1) {
|
||||
clif_displaymessage(sd->fd,"Message number cannot be negative or zero.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mail_delete(sd,index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atcommand_sendmail(const int fd, struct map_session_data* sd, const char* command, const char* message)
|
||||
{
|
||||
char name[NAME_LENGTH],text[80];
|
||||
|
||||
if(!mail_server_enable)
|
||||
return 0;
|
||||
|
||||
nullpo_retr(-1, sd);
|
||||
|
||||
if (!message || !*message) {
|
||||
clif_displaymessage(sd->fd,"You must specify a recipient and a message.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((sscanf(message, "\"%23[^\"]\" %79[^\n]", name, text) < 2) &&
|
||||
(sscanf(message, "%23s %79[^\n]", name, text) < 2)) {
|
||||
clif_displaymessage(sd->fd,"You must specify a recipient and a message.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(strlen(command)==17) // @sendprioritymail
|
||||
mail_send(sd,name,text,1);
|
||||
else
|
||||
mail_send(sd,name,text,0);
|
||||
nullpo_retr(0,sd);
|
||||
|
||||
mail_openmail(sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -255,13 +255,7 @@ enum AtCommandType {
|
||||
AtCommand_HappyHappyJoyJoy,
|
||||
// SQL-only commands start
|
||||
#ifndef TXT_ONLY
|
||||
AtCommand_CheckMail, // [Valaris]
|
||||
AtCommand_ListMail, // [Valaris]
|
||||
AtCommand_ListNewMail, // [Valaris]
|
||||
AtCommand_ReadMail, // [Valaris]
|
||||
AtCommand_SendMail, // [Valaris]
|
||||
AtCommand_DeleteMail, // [Valaris]
|
||||
AtCommand_SendPriorityMail, // [Valaris]
|
||||
AtCommand_Mail, // [Mail System]
|
||||
AtCommand_RefreshOnline, // [Valaris]
|
||||
// SQL-only commands end
|
||||
#endif
|
||||
|
423
src/map/clif.c
423
src/map/clif.c
@ -36,6 +36,7 @@
|
||||
#include "log.h"
|
||||
#include "irc.h"
|
||||
#include "clif.h"
|
||||
#include "mail.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -2500,7 +2501,7 @@ int clif_updatestatus(struct map_session_data *sd,int type)
|
||||
|
||||
case SP_ZENY:
|
||||
WFIFOW(fd,0)=0xb1;
|
||||
WFIFOL(fd,4)=sd->status.zeny;
|
||||
WFIFOL(fd,4)=sd->status.zeny - sd->mail.zeny;
|
||||
break;
|
||||
case SP_BASEEXP:
|
||||
WFIFOW(fd,0)=0xb1;
|
||||
@ -11294,6 +11295,409 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd)
|
||||
pc_delitem(sd, item_position, 1, 0);
|
||||
}
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
|
||||
/*==========================================
|
||||
* MAIL SYSTEM
|
||||
* By Zephyrus
|
||||
*------------------------------------------
|
||||
* Opens Mail Window on Client
|
||||
*------------------------------------------*/
|
||||
void clif_Mail_openmail(int fd)
|
||||
{
|
||||
WFIFOHEAD(fd,packet_len(0x260));
|
||||
WFIFOW(fd,0) = 0x260;
|
||||
WFIFOL(fd,2) = 0;
|
||||
WFIFOSET(fd,packet_len(0x260));
|
||||
}
|
||||
/*------------------------------------------
|
||||
* Send Inbox Data to Client
|
||||
*------------------------------------------*/
|
||||
void clif_Mail_refreshinbox(struct map_session_data *sd)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
struct mail_data *md = &sd->mail.inbox;
|
||||
struct mail_message *msg;
|
||||
int len, i, j;
|
||||
|
||||
len = 8 + (73 * md->amount);
|
||||
|
||||
WFIFOHEAD(fd,len);
|
||||
WFIFOW(fd,0) = 0x240;
|
||||
WFIFOW(fd,2) = len;
|
||||
WFIFOL(fd,4) = md->amount;
|
||||
for( i = j = 0; i < MAX_MAIL_INBOX && j < md->amount; i++ )
|
||||
{
|
||||
msg = &md->msg[i];
|
||||
if (msg->id < 1)
|
||||
continue; // Deleted Message
|
||||
|
||||
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;
|
||||
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 < MAX_MAIL_INBOX && (md->satured || md->changed) )
|
||||
intif_Mail_requestinbox(sd->status.char_id, 1);
|
||||
else
|
||||
clif_Mail_refreshinbox(sd);
|
||||
|
||||
mail_removeitem(sd, 0);
|
||||
mail_removezeny(sd, 0);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Read Message
|
||||
*------------------------------------------*/
|
||||
void clif_Mail_read(struct map_session_data *sd, int mail_id)
|
||||
{
|
||||
int i, fd = sd->fd;
|
||||
|
||||
ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
|
||||
if (i < MAX_MAIL_INBOX)
|
||||
{
|
||||
struct mail_message *msg = &sd->mail.inbox.msg[i];
|
||||
struct item *item = &msg->item;
|
||||
struct item_data *data;
|
||||
int msg_len = strlen(msg->body), len;
|
||||
|
||||
if( msg_len == 0 ) {
|
||||
strcpy(msg->body, "(no message)");
|
||||
msg_len = strlen(msg->body);
|
||||
}
|
||||
|
||||
len = 101 + msg_len;
|
||||
|
||||
WFIFOHEAD(fd,len);
|
||||
WFIFOW(fd,0) = 0x242;
|
||||
WFIFOW(fd,2) = len;
|
||||
WFIFOL(fd,4) = msg->id;
|
||||
memcpy(WFIFOP(fd, 8), msg->title, MAIL_TITLE_LENGTH);
|
||||
memcpy(WFIFOP(fd,48), msg->send_name, NAME_LENGTH);
|
||||
WFIFOL(fd,72) = 0;
|
||||
WFIFOL(fd,76) = msg->zeny;
|
||||
|
||||
if (item->nameid)
|
||||
{
|
||||
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,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,99) = (unsigned char)msg_len;
|
||||
memcpy(WFIFOP(fd,100), msg->body, msg_len);
|
||||
WFIFOB(fd,len - 1) = 0x00;
|
||||
WFIFOSET(fd,len);
|
||||
|
||||
if (!msg->read) {
|
||||
msg->read = 1;
|
||||
intif_Mail_read(mail_id);
|
||||
clif_parse_Mail_refreshinbox(fd, sd);
|
||||
}
|
||||
}
|
||||
else
|
||||
ShowWarning("clif_parse_Mail_read: account %d trying to read a message not the inbox.\n", sd->status.account_id);
|
||||
}
|
||||
|
||||
void clif_parse_Mail_read(int fd, struct map_session_data *sd)
|
||||
{
|
||||
nullpo_retv(sd);
|
||||
clif_Mail_read(sd, RFIFOL(fd,2));
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Get Attachment from Message
|
||||
*------------------------------------------*/
|
||||
void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
|
||||
{
|
||||
int i, mail_id = RFIFOL(fd,2);
|
||||
nullpo_retv(sd);
|
||||
|
||||
ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
|
||||
if (i < MAX_MAIL_INBOX)
|
||||
{
|
||||
if (sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1))
|
||||
return;
|
||||
|
||||
if (sd->mail.inbox.msg[i].item.nameid > 0)
|
||||
{
|
||||
struct item_data *data;
|
||||
unsigned int weight;
|
||||
|
||||
if ((data = itemdb_search(sd->mail.inbox.msg[i].item.nameid)) == NULL)
|
||||
return;
|
||||
|
||||
weight = data->weight * sd->mail.inbox.msg[i].item.amount;
|
||||
if (weight > sd->max_weight - sd->weight)
|
||||
{
|
||||
clif_displaymessage(fd, "Attachment to heavy for you...");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sd->mail.inbox.msg[i].zeny = 0;
|
||||
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, short flag)
|
||||
{
|
||||
int fd = sd->fd;
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
int i;
|
||||
ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
|
||||
if( i < MAX_MAIL_INBOX )
|
||||
{
|
||||
memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message));
|
||||
sd->mail.inbox.amount--;
|
||||
}
|
||||
}
|
||||
|
||||
WFIFOHEAD(fd, packet_len(0x257));
|
||||
WFIFOW(fd,0) = 0x257;
|
||||
WFIFOL(fd,2) = mail_id;
|
||||
WFIFOW(fd,6) = flag;
|
||||
WFIFOSET(fd, packet_len(0x257));
|
||||
|
||||
if( !flag && sd->mail.inbox.satured )
|
||||
intif_Mail_requestinbox(sd->status.char_id, 1); // Reload the Mail Inbox
|
||||
}
|
||||
|
||||
void clif_parse_Mail_delete(int fd, struct map_session_data *sd)
|
||||
{
|
||||
int i, mail_id = RFIFOL(fd,2);
|
||||
nullpo_retv(sd);
|
||||
|
||||
ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
|
||||
if (i < MAX_MAIL_INBOX)
|
||||
{
|
||||
struct mail_message *msg = &sd->mail.inbox.msg[i];
|
||||
|
||||
if( (msg->item.nameid > 0 && msg->item.amount > 0) || msg->zeny > 0 )
|
||||
{
|
||||
clif_Mail_delete(sd, 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
|
||||
*------------------------------------------*/
|
||||
void clif_parse_Mail_return(int fd, struct map_session_data *sd)
|
||||
{
|
||||
int i, mail_id = RFIFOL(fd,2);
|
||||
nullpo_retv(sd);
|
||||
|
||||
ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
|
||||
if (i < MAX_MAIL_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, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
|
||||
if (i < MAX_MAIL_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));
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Set Attachment
|
||||
*------------------------------------------*/
|
||||
void clif_parse_Mail_setattach(int fd, struct map_session_data *sd)
|
||||
{
|
||||
int idx = RFIFOW(fd,2), amount = RFIFOL(fd,4);
|
||||
char flag;
|
||||
|
||||
nullpo_retv(sd);
|
||||
if (idx < 0 || amount < 0)
|
||||
return;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Mail Window Operation
|
||||
*------------------------------------------*/
|
||||
void clif_parse_Mail_winopen(int fd, struct map_session_data *sd)
|
||||
{
|
||||
int flag = RFIFOW(fd,2);
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (!flag || flag == 1)
|
||||
mail_removeitem(sd, 0);
|
||||
if (!flag || flag == 2)
|
||||
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));
|
||||
}
|
||||
|
||||
void clif_parse_Mail_send(int fd, struct map_session_data *sd)
|
||||
{
|
||||
struct map_session_data *rd;
|
||||
struct mail_message *msg;
|
||||
int body_len;
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( RFIFOW(fd,2) < 69 ) {
|
||||
ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 )
|
||||
{
|
||||
clif_displaymessage(sd->fd,"Cannot send mails too fast!!.");
|
||||
clif_Mail_send(fd, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
body_len = RFIFOB(fd,68);
|
||||
rd = map_nick2sd_nocase(RFIFOP(fd,4));
|
||||
|
||||
if (rd && rd == sd) {
|
||||
clif_Mail_send(fd, 1);
|
||||
mail_removeitem(sd,0);
|
||||
mail_removezeny(sd,0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (body_len > MAIL_BODY_LENGTH)
|
||||
body_len = MAIL_BODY_LENGTH;
|
||||
|
||||
msg = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1);
|
||||
|
||||
if (mail_getattach(sd, msg))
|
||||
{
|
||||
msg->send_id = sd->status.char_id;
|
||||
safestrncpy(msg->send_name, sd->status.name, NAME_LENGTH);
|
||||
|
||||
if (rd) {
|
||||
msg->dest_id = rd->status.char_id;
|
||||
safestrncpy(msg->dest_name, rd->status.name, NAME_LENGTH);
|
||||
} else {
|
||||
msg->dest_id = 0;
|
||||
safestrncpy(msg->dest_name, RFIFOP(fd,4), NAME_LENGTH);
|
||||
}
|
||||
|
||||
memcpy(msg->title, RFIFOP(fd,28), MAIL_TITLE_LENGTH);
|
||||
|
||||
if (body_len)
|
||||
memcpy(msg->body, RFIFOP(fd,69), body_len);
|
||||
else
|
||||
memset(msg->body, 0x00, MAIL_BODY_LENGTH);
|
||||
|
||||
msg->timestamp = (int)mail_calctimes();
|
||||
intif_Mail_send(sd->status.account_id, msg);
|
||||
|
||||
sd->cansendmail_tick = gettick() + 1000; // 5 Seconds flood Protection
|
||||
}
|
||||
else
|
||||
{
|
||||
mail_removeitem(sd,0);
|
||||
mail_removezeny(sd,0);
|
||||
clif_Mail_send(sd->fd, 1); // Fail
|
||||
}
|
||||
|
||||
aFree(msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*==========================================
|
||||
* ƒpƒPƒbƒgƒfƒoƒbƒO
|
||||
*------------------------------------------*/
|
||||
@ -11551,10 +11955,10 @@ static int packetdb_readdb(void)
|
||||
//#0x0240
|
||||
-1, -1, -1, -1, -1, 3, 4, 8, -1, 3, 70, 4, 8, 12, 4, 10,
|
||||
3, 32, -1, 3, 3, 5, 5, 8, 2, 3, -1, -1, 4, -1, 4, 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,
|
||||
6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
//#0x0280
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 18, 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,191, 0, 0, 0, 0, 0, 0,
|
||||
@ -11705,6 +12109,17 @@ static int packetdb_readdb(void)
|
||||
{clif_parse_StoragePassword,"storagepassword"},
|
||||
{clif_parse_Hotkey,"hotkey"},
|
||||
{clif_parse_AutoRevive,"autorevive"},
|
||||
#ifndef TXT_ONLY
|
||||
// MAIL SYSTEM
|
||||
{clif_parse_Mail_refreshinbox,"mailrefresh"},
|
||||
{clif_parse_Mail_read,"mailread"},
|
||||
{clif_parse_Mail_getattach,"mailgetattach"},
|
||||
{clif_parse_Mail_delete,"maildelete"},
|
||||
{clif_parse_Mail_return,"mailreturn"},
|
||||
{clif_parse_Mail_setattach,"mailsetattach"},
|
||||
{clif_parse_Mail_winopen,"mailwinopen"},
|
||||
{clif_parse_Mail_send,"mailsend"},
|
||||
#endif
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
|
@ -382,5 +382,15 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
|
||||
int do_final_clif(void);
|
||||
int do_init_clif(void);
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
// 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, short flag);
|
||||
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_refreshinbox(struct map_session_data *sd);
|
||||
#endif
|
||||
|
||||
#endif /* _CLIF_H_ */
|
||||
|
281
src/map/intif.c
281
src/map/intif.c
@ -18,6 +18,7 @@
|
||||
#include "pet.h"
|
||||
#include "atcommand.h"
|
||||
#include "mercenary.h" //albator
|
||||
#include "mail.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
@ -32,7 +33,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, 0, 0, 0, 0, 0, 0, 0, 0, //0x3840
|
||||
9, 9,-1,14, 0, 0, 0, 0, -1, 0,-1,12, 14,-1, 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,
|
||||
@ -1458,6 +1459,275 @@ int intif_parse_DeleteHomunculusOk(int fd)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* MAIL SYSTEM
|
||||
* By Zephyrus
|
||||
*------------------------------------------
|
||||
* Inbox Request
|
||||
* flag: 0 Update Inbox | 1 OpenMail
|
||||
*------------------------------------------*/
|
||||
#ifndef TXT_ONLY
|
||||
|
||||
int intif_Mail_requestinbox(int char_id, unsigned char flag)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
WFIFOHEAD(inter_fd,7);
|
||||
WFIFOW(inter_fd,0) = 0x3048;
|
||||
WFIFOL(inter_fd,2) = char_id;
|
||||
WFIFOB(inter_fd,6) = flag;
|
||||
WFIFOSET(inter_fd,7);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intif_parse_Mail_inboxreceived(int fd)
|
||||
{
|
||||
struct map_session_data *sd;
|
||||
unsigned char flag = RFIFOB(fd,8);
|
||||
|
||||
sd = map_charid2sd( RFIFOL(fd,4) );
|
||||
|
||||
if (sd == NULL)
|
||||
{
|
||||
if (battle_config.error_log)
|
||||
ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sd->state.finalsave)
|
||||
return 1;
|
||||
|
||||
if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data))
|
||||
{
|
||||
if (battle_config.error_log)
|
||||
ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data));
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&sd->mail.inbox, 0, sizeof(struct mail_data));
|
||||
memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data));
|
||||
|
||||
if (flag)
|
||||
clif_Mail_refreshinbox(sd);
|
||||
else
|
||||
{
|
||||
char output[128];
|
||||
sprintf(output, "You have %d new emails (%d unreaded)", sd->mail.inbox.unchecked, sd->mail.inbox.unreaded + sd->mail.inbox.unchecked);
|
||||
clif_disp_onlyself(sd, output, strlen(output));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------
|
||||
* Mail Readed
|
||||
*------------------------------------------*/
|
||||
int intif_Mail_read(int mail_id)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
WFIFOHEAD(inter_fd,6);
|
||||
WFIFOW(inter_fd,0) = 0x3049;
|
||||
WFIFOL(inter_fd,2) = mail_id;
|
||||
WFIFOSET(inter_fd,6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------
|
||||
* Get Attachment
|
||||
*------------------------------------------*/
|
||||
int intif_Mail_getattach(int char_id, int mail_id)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
WFIFOHEAD(inter_fd,10);
|
||||
WFIFOW(inter_fd,0) = 0x304a;
|
||||
WFIFOL(inter_fd,2) = char_id;
|
||||
WFIFOL(inter_fd,6) = mail_id;
|
||||
WFIFOSET(inter_fd, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intif_parse_Mail_getattach(int fd)
|
||||
{
|
||||
struct map_session_data *sd;
|
||||
struct item *item;
|
||||
int zeny = RFIFOL(fd,8);
|
||||
|
||||
sd = map_charid2sd( RFIFOL(fd,4) );
|
||||
|
||||
if (sd == NULL)
|
||||
{
|
||||
if (battle_config.error_log)
|
||||
ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sd->state.finalsave)
|
||||
return 1;
|
||||
|
||||
if (RFIFOW(fd,2) - 12 != sizeof(struct item))
|
||||
{
|
||||
if (battle_config.error_log)
|
||||
ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (zeny > 0)
|
||||
{
|
||||
sd->status.zeny += zeny;
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------
|
||||
* Delete Message
|
||||
*------------------------------------------*/
|
||||
int intif_Mail_delete(int char_id, int mail_id)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
WFIFOHEAD(inter_fd,10);
|
||||
WFIFOW(inter_fd,0) = 0x304b;
|
||||
WFIFOL(inter_fd,2) = char_id;
|
||||
WFIFOL(inter_fd,6) = mail_id;
|
||||
WFIFOSET(inter_fd,10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intif_parse_Mail_delete(int fd)
|
||||
{
|
||||
struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2));
|
||||
int mail_id = RFIFOL(fd,6);
|
||||
short flag = RFIFOW(fd,10);
|
||||
|
||||
if (sd == NULL)
|
||||
{
|
||||
if (battle_config.error_log)
|
||||
ShowError("intif_parse_Mail_delete: char not found %d\n",RFIFOL(fd,2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sd->state.finalsave)
|
||||
return 1;
|
||||
|
||||
clif_Mail_delete(sd, mail_id, flag);
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------
|
||||
* Return Message
|
||||
*------------------------------------------*/
|
||||
int intif_Mail_return(int char_id, int mail_id)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
WFIFOHEAD(inter_fd,10);
|
||||
WFIFOW(inter_fd,0) = 0x304c;
|
||||
WFIFOL(inter_fd,2) = char_id;
|
||||
WFIFOL(inter_fd,6) = mail_id;
|
||||
WFIFOSET(inter_fd,10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
return 1;
|
||||
|
||||
clif_Mail_return(sd, mail_id, new_mail);
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------
|
||||
* Send Mail
|
||||
*------------------------------------------*/
|
||||
int intif_Mail_send(int account_id, struct mail_message *msg)
|
||||
{
|
||||
int len = sizeof(struct mail_message) + 8;
|
||||
|
||||
if (CheckForCharServer())
|
||||
return 0;
|
||||
|
||||
WFIFOHEAD(inter_fd,len);
|
||||
WFIFOW(inter_fd,0) = 0x304d;
|
||||
WFIFOW(inter_fd,2) = len;
|
||||
WFIFOL(inter_fd,4) = account_id;
|
||||
memcpy(WFIFOP(inter_fd,8), msg, sizeof(struct mail_message));
|
||||
WFIFOSET(inter_fd,len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (sd == NULL && mail_id > 0)
|
||||
{
|
||||
if (battle_config.error_log)
|
||||
ShowError("intif_parse_Mail_send: char not found %d\n",RFIFOL(fd,2));
|
||||
|
||||
// If sd = NULL attachment haven't been removed from sender inventory.
|
||||
intif_Mail_delete(dest_id, mail_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mail_id > 0)
|
||||
{
|
||||
struct map_session_data *rd = map_charid2sd(dest_id);
|
||||
|
||||
mail_removeitem(sd, 1);
|
||||
mail_removezeny(sd, 1);
|
||||
|
||||
if (rd != NULL)
|
||||
{
|
||||
char title[MAIL_TITLE_LENGTH];
|
||||
memcpy(title, RFIFOP(fd,16), RFIFOW(fd,2) - 16);
|
||||
|
||||
rd->mail.inbox.changed = 1;
|
||||
clif_Mail_new(rd->fd, mail_id, sd->status.name, title);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Return the items to the owner
|
||||
mail_removeitem(sd, 0);
|
||||
mail_removezeny(sd, 0);
|
||||
}
|
||||
|
||||
clif_Mail_send(sd->fd, (mail_id > 0)?0:1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// inter serverからの通信
|
||||
// エラーがあれば0(false)を返すこと
|
||||
@ -1528,6 +1798,15 @@ int intif_parse(int fd)
|
||||
case 0x3841: intif_parse_GuildCastleDataSave(fd); break;
|
||||
case 0x3842: intif_parse_GuildCastleAllDataLoad(fd); break;
|
||||
case 0x3843: intif_parse_GuildMasterChanged(fd); break;
|
||||
// Mail System
|
||||
#ifndef TXT_ONLY
|
||||
case 0x3848: intif_parse_Mail_inboxreceived(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;
|
||||
case 0x384d: intif_parse_Mail_send(fd); break;
|
||||
#endif
|
||||
// End of Mail System
|
||||
case 0x3880: intif_parse_CreatePet(fd); break;
|
||||
case 0x3881: intif_parse_RecvPetData(fd); break;
|
||||
case 0x3882: intif_parse_SavePetOk(fd); break;
|
||||
|
@ -74,6 +74,15 @@ int intif_homunculus_requestload(int account_id, int homun_id);
|
||||
int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh);
|
||||
int intif_homunculus_requestdelete(int homun_id);
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
// MAIL SYSTEM
|
||||
int intif_Mail_requestinbox(int char_id, unsigned char flag);
|
||||
int intif_Mail_read(int mail_id);
|
||||
int intif_Mail_getattach(int char_id, int mail_id);
|
||||
int intif_Mail_delete(int char_id, int mail_id);
|
||||
int intif_Mail_return(int char_id, int mail_id);
|
||||
int intif_Mail_send(int account_id, struct mail_message *msg);
|
||||
#endif
|
||||
|
||||
int CheckForCharServer(void);
|
||||
|
||||
|
399
src/map/mail.c
399
src/map/mail.c
@ -3,365 +3,122 @@
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
|
||||
#include "../common/strlib.h"
|
||||
#include "../common/socket.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/nullpo.h"
|
||||
#include "../common/showmsg.h"
|
||||
|
||||
#include "map.h"
|
||||
#include "clif.h"
|
||||
#include "chrif.h"
|
||||
#include "intif.h"
|
||||
#include "atcommand.h"
|
||||
#include "pc.h"
|
||||
#include "mail.h"
|
||||
#include "itemdb.h"
|
||||
#include "clif.h"
|
||||
#include "pc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int MAIL_CHECK_TIME = 120000;
|
||||
int mail_timer;
|
||||
|
||||
/// type: 0 - mail check at login, silent if there aren't any new messages
|
||||
/// 1 - @checkmail, just print the number of messages
|
||||
/// 2 - @listmail, shows both read and unread messages
|
||||
/// 3 - @listnewmail, shows only unread messages
|
||||
int mail_check(struct map_session_data* sd, int type)
|
||||
time_t mail_calctimes(void)
|
||||
{
|
||||
int i = 0, new_ = 0, priority = 0; // counters
|
||||
char message[80];
|
||||
|
||||
nullpo_retr (0, sd);
|
||||
|
||||
// retrieve all existing messages for this player
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` FROM `%s` WHERE `to_account_id` = %d ORDER by `message_id`", mail_db, sd->status.account_id) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( Sql_NumRows(mail_handle) == 0)
|
||||
{
|
||||
clif_displaymessage(sd->fd, msg_txt(516)); // "You have no messages."
|
||||
Sql_FreeResult(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
|
||||
{
|
||||
char* data;
|
||||
int message_id;
|
||||
int to_account_id;
|
||||
char from_char_name[NAME_LENGTH];
|
||||
bool read_flag, priority_flag, check_flag;
|
||||
|
||||
Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 1, &data, NULL); to_account_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name));
|
||||
Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data);
|
||||
Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data);
|
||||
Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data);
|
||||
|
||||
i++;
|
||||
|
||||
if( !check_flag )
|
||||
{
|
||||
// mark this message as checked
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
}
|
||||
|
||||
if( !read_flag )
|
||||
{
|
||||
new_++;
|
||||
if(priority_flag)
|
||||
priority++;
|
||||
|
||||
if( type == 2 || type == 3 )
|
||||
{
|
||||
if( priority_flag )
|
||||
{
|
||||
snprintf(message, 80, msg_txt(511), i, from_char_name);
|
||||
clif_displaymessage(sd->fd, message); // "%d - From : %s (New - Priority)"
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(message, 80, msg_txt(512), i, from_char_name);
|
||||
clif_displaymessage(sd->fd, message); // "%d - From : %s (New)"
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( type == 2 )
|
||||
{
|
||||
snprintf(message, 80, msg_txt(513), i, from_char_name);
|
||||
clif_displaymessage(sd->fd, message); // "%d - From : %s"
|
||||
}
|
||||
}
|
||||
|
||||
Sql_FreeResult(mail_handle);
|
||||
|
||||
if( new_ > 0 && (type == 0 || type == 1) )
|
||||
{
|
||||
sprintf(message, msg_txt(514), new_);
|
||||
clif_displaymessage(sd->fd, message); // "You have %d unread messages."
|
||||
if (priority > 0)
|
||||
{
|
||||
sprintf(message, msg_txt(515), priority);
|
||||
clif_displaymessage(sd->fd, message); // "You have %d unread priority messages."
|
||||
}
|
||||
}
|
||||
if( new_ == 0 && type != 0 )
|
||||
{
|
||||
clif_displaymessage(sd->fd, msg_txt(516)); // "You have no unread messages."
|
||||
}
|
||||
|
||||
return 0;
|
||||
time_t temp = time(NULL);
|
||||
return mktime(localtime(&temp));
|
||||
}
|
||||
|
||||
/// displays the selected message
|
||||
int mail_read(struct map_session_data* sd, int index)
|
||||
int mail_removeitem(struct map_session_data *sd, short flag)
|
||||
{
|
||||
char* data;
|
||||
int message_id;
|
||||
char from_char_name[NAME_LENGTH];
|
||||
char message[80];
|
||||
bool read_flag, priority_flag, check_flag;
|
||||
char output[100];
|
||||
nullpo_retr(0,sd);
|
||||
|
||||
nullpo_retr(0, sd);
|
||||
|
||||
// retrieve the 'index'-th message
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`from_char_name`,`message`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = %d ORDER by `message_id` LIMIT %d, 1", mail_db, sd->status.account_id, index-1) )
|
||||
if( sd->mail.amount )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
return 0;
|
||||
if (flag)
|
||||
pc_delitem(sd, sd->mail.index, sd->mail.amount, 1);
|
||||
else
|
||||
clif_additem(sd, sd->mail.index, sd->mail.amount, 0);
|
||||
}
|
||||
|
||||
if( 0 == Sql_NumRows(mail_handle) )
|
||||
{
|
||||
clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found."
|
||||
Sql_FreeResult(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( SQL_ERROR == Sql_NextRow(mail_handle) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
Sql_FreeResult(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 1, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name));
|
||||
Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(message, data, sizeof(message));
|
||||
Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data);
|
||||
Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data);
|
||||
Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data);
|
||||
|
||||
Sql_FreeResult(mail_handle);
|
||||
|
||||
// mark mail as checked
|
||||
if( !check_flag )
|
||||
{
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
}
|
||||
|
||||
sprintf(output, msg_txt(518), from_char_name);
|
||||
clif_displaymessage(sd->fd, output); // "Reading message from %s"
|
||||
clif_displaymessage(sd->fd, message);
|
||||
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `read_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
sd->mail.index = 0;
|
||||
sd->mail.amount = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// message deletion
|
||||
int mail_delete(struct map_session_data* sd, int index)
|
||||
int mail_removezeny(struct map_session_data *sd, short flag)
|
||||
{
|
||||
char* data;
|
||||
int message_id;
|
||||
bool read_flag, priority_flag, check_flag;
|
||||
nullpo_retr(0,sd);
|
||||
|
||||
nullpo_retr (0, sd);
|
||||
if (flag && sd->mail.zeny > 0)
|
||||
sd->status.zeny -= sd->mail.zeny;
|
||||
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = %d ORDER by `message_id` LIMIT %d, 1", mail_db, sd->status.account_id, index-1) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
sd->mail.zeny = 0;
|
||||
clif_updatestatus(sd, SP_ZENY);
|
||||
|
||||
if( 0 == Sql_NumRows(mail_handle) )
|
||||
{
|
||||
clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found."
|
||||
Sql_FreeResult(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( SQL_ERROR == Sql_NextRow(mail_handle) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
Sql_FreeResult(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
|
||||
Sql_GetData(mail_handle, 1, &data, NULL); read_flag = (bool)atoi(data);
|
||||
Sql_GetData(mail_handle, 2, &data, NULL); priority_flag = (bool)atoi(data);
|
||||
Sql_GetData(mail_handle, 3, &data, NULL); check_flag = (bool)atoi(data);
|
||||
|
||||
Sql_FreeResult(mail_handle);
|
||||
|
||||
if( !read_flag && priority_flag )
|
||||
{
|
||||
clif_displaymessage(sd->fd,msg_txt(519)); // "Cannot delete unread priority mail."
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !check_flag )
|
||||
{
|
||||
clif_displaymessage(sd->fd,msg_txt(520)); // "You have received new mail, use @listmail before deleting."
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "DELETE FROM `%s` WHERE `message_id` = %d", mail_db, message_id) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
clif_displaymessage(sd->fd,msg_txt(521)); // "Message deleted."
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// for sending normal and priority messages
|
||||
int mail_send(struct map_session_data* sd, char* name, char* message, int flag)
|
||||
char mail_setitem(struct map_session_data *sd, int idx, int amount)
|
||||
{
|
||||
SqlStmt* stmt;
|
||||
nullpo_retr(-1,sd);
|
||||
|
||||
nullpo_retr (0, sd);
|
||||
if (idx == 0)
|
||||
{ // Zeny Transfer
|
||||
if (amount < 0)
|
||||
return 2;
|
||||
if (amount > sd->status.zeny)
|
||||
amount = sd->status.zeny;
|
||||
|
||||
if( pc_isGM(sd) < 80 && sd->mail_counter > 0 )
|
||||
{
|
||||
clif_displaymessage(sd->fd,msg_txt(522)); // "You must wait 10 minutes before sending another message"
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( strcmp(name,"*") == 0 && pc_isGM(sd) < 80 )
|
||||
{
|
||||
clif_displaymessage(sd->fd, msg_txt(523)); // "Access Denied."
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( strcmp(name,"*") == 0 )
|
||||
{
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `account_id` FROM `%s` WHERE `account_id` != '%d' ORDER BY `account_id`", char_db, sd->status.account_id) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
sd->mail.zeny = amount;
|
||||
clif_updatestatus(sd, SP_ZENY);
|
||||
}
|
||||
else
|
||||
{ // Item Transfer
|
||||
idx -= 2;
|
||||
mail_removeitem(sd, 0);
|
||||
|
||||
if( idx < 0 || idx > MAX_INVENTORY )
|
||||
return 2;
|
||||
if( amount < 0 || amount > sd->status.inventory[idx].amount )
|
||||
return 2;
|
||||
if( itemdb_isdropable(&sd->status.inventory[idx], pc_isGM(sd)) == 0 )
|
||||
return 2;
|
||||
|
||||
sd->mail.index = idx;
|
||||
sd->mail.amount = amount;
|
||||
|
||||
clif_delitem(sd, idx, amount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mail_getattach(struct map_session_data *sd, struct mail_message *msg)
|
||||
{
|
||||
int n;
|
||||
|
||||
nullpo_retr(0,sd);
|
||||
nullpo_retr(0,msg);
|
||||
|
||||
if( sd->mail.zeny < 0 || sd->mail.zeny > sd->status.zeny )
|
||||
return 0;
|
||||
|
||||
n = sd->mail.index;
|
||||
if( sd->mail.amount )
|
||||
{
|
||||
char name_[2*NAME_LENGTH];
|
||||
Sql_EscapeString(mail_handle, name_, name);
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `account_id` FROM `%s` WHERE `name` = '%s'", char_db, name_) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
if( sd->status.inventory[n].amount < sd->mail.amount )
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item));
|
||||
msg->item.amount = sd->mail.amount;
|
||||
}
|
||||
|
||||
if( 0 == Sql_NumRows(mail_handle) )
|
||||
{
|
||||
clif_displaymessage(sd->fd,msg_txt(524)); // "Character does not exist."
|
||||
Sql_FreeResult(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
msg->zeny = sd->mail.zeny;
|
||||
|
||||
stmt = SqlStmt_Malloc(mail_handle);
|
||||
SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`) VALUES (?, ?, '%d', ?, ?, '%d')", mail_db, sd->status.account_id, flag);
|
||||
SqlStmt_BindParam(stmt, 1, SQLDT_STRING, name, strnlen(name, NAME_LENGTH));
|
||||
SqlStmt_BindParam(stmt, 2, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH));
|
||||
SqlStmt_BindParam(stmt, 3, SQLDT_STRING, message, strnlen(message, 80));
|
||||
|
||||
while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
|
||||
{
|
||||
int id;
|
||||
char* data;
|
||||
Sql_GetData(mail_handle, 0, &data, NULL); id = atoi(data);
|
||||
SqlStmt_BindParam(stmt, 0, SQLDT_INT, &id, sizeof(id));
|
||||
if( SQL_ERROR == SqlStmt_Execute(stmt) )
|
||||
SqlStmt_ShowDebug(stmt);
|
||||
}
|
||||
Sql_FreeResult(mail_handle);
|
||||
SqlStmt_Free(stmt);
|
||||
|
||||
if(pc_isGM(sd) < 80)
|
||||
sd->mail_counter = 5;
|
||||
|
||||
clif_displaymessage(sd->fd,msg_txt(525)); // "Mail has been sent."
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// invoked every MAIL_CHECK_TIME ms, decreases the send blocking counter
|
||||
static int mail_check_timer_sub(struct map_session_data* sd, va_list va)
|
||||
int mail_openmail(struct map_session_data *sd)
|
||||
{
|
||||
if(sd->mail_counter > 0)
|
||||
sd->mail_counter--;
|
||||
return 0;
|
||||
}
|
||||
nullpo_retr(0,sd);
|
||||
|
||||
/// periodically checks for new messages and notifies about them
|
||||
int mail_check_timer(int tid, unsigned int tick, int id, int data)
|
||||
{
|
||||
if(mail_timer != tid)
|
||||
if( sd->state.finalsave == 1 || sd->state.storage_flag || sd->vender_id || sd->state.trading )
|
||||
return 0;
|
||||
|
||||
mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0);
|
||||
|
||||
// fetch account ids of people who received new mail since the last iteration
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `to_account_id` FROM `%s` WHERE `read_flag` = '0' AND `check_flag` = '0'", mail_db) )
|
||||
{
|
||||
Sql_ShowDebug(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
|
||||
{
|
||||
char* id;
|
||||
struct map_session_data* sd;
|
||||
Sql_GetData(mail_handle, 0, &id, NULL);
|
||||
if( (sd = map_id2sd(atoi(id))) != NULL )
|
||||
clif_displaymessage(sd->fd, msg_txt(526)); // "You have new mail."
|
||||
}
|
||||
|
||||
Sql_FreeResult(mail_handle);
|
||||
|
||||
// decrease the send-blocking counter
|
||||
clif_foreachclient(mail_check_timer_sub);
|
||||
|
||||
// The 'check_flag' indicates whether the player was informed about the message.
|
||||
// All online players were notified by the above code, and offline players will get the notice at next login.
|
||||
// Therefore it is safe to simply set the flag to '1' for all existing mails.
|
||||
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `check_flag` = 0", mail_db) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_init_mail(void)
|
||||
{
|
||||
add_timer_func_list(mail_check_timer, "mail_check_timer");
|
||||
mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0);
|
||||
clif_Mail_openmail(sd->fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4,11 +4,14 @@
|
||||
#ifndef _MAIL_H_
|
||||
#define _MAIL_H_
|
||||
|
||||
int mail_check(struct map_session_data *sd, int type);
|
||||
int mail_read(struct map_session_data *sd, int index);
|
||||
int mail_delete(struct map_session_data *sd, int index);
|
||||
int mail_send(struct map_session_data *sd, char *name, char *message, int flag);
|
||||
#include "../common/mmo.h"
|
||||
|
||||
int do_init_mail(void);
|
||||
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);
|
||||
int mail_openmail(struct map_session_data *sd);
|
||||
|
||||
#endif /* _MAIL_H_ */
|
||||
|
@ -75,16 +75,6 @@ char log_db_pw[32] = "ragnarok";
|
||||
char log_db[32] = "log";
|
||||
Sql* logmysql_handle;
|
||||
|
||||
// mail system
|
||||
int mail_server_enable = 0;
|
||||
char mail_server_ip[32] = "127.0.0.1";
|
||||
int mail_server_port = 3306;
|
||||
char mail_server_id[32] = "ragnarok";
|
||||
char mail_server_pw[32] = "ragnarok";
|
||||
char mail_server_db[32] = "ragnarok";
|
||||
char mail_db[32] = "mail";
|
||||
Sql* mail_handle;
|
||||
|
||||
#endif /* not TXT_ONLY */
|
||||
|
||||
int lowest_gm_level = 1;
|
||||
@ -1857,6 +1847,21 @@ struct map_session_data * map_nick2sd(const char *nick)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct map_session_data * map_nick2sd_nocase(const char *nick)
|
||||
{
|
||||
int i, users;
|
||||
struct map_session_data **pl_allsd;
|
||||
|
||||
pl_allsd = map_getallusers(&users);
|
||||
for (i = 0; i < users; i++)
|
||||
{
|
||||
if ( !strcmp(pl_allsd[i]->status.name, nick) )
|
||||
return pl_allsd[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* id番?の物を探す
|
||||
* 一三bjectの場合は配列を引くのみ
|
||||
@ -2888,22 +2893,6 @@ int inter_config_read(char *cfgName)
|
||||
strcpy(log_db_pw, w2);
|
||||
} else if(strcmpi(w1,"log_db_port")==0) {
|
||||
log_db_port = atoi(w2);
|
||||
// Mail Server SQL
|
||||
} else if(strcmpi(w1,"mail_server_enable")==0){
|
||||
mail_server_enable = config_switch(w2);
|
||||
ShowStatus ("Using Mail Server: %s\n",w2);
|
||||
} else if(strcmpi(w1,"mail_server_ip")==0){
|
||||
strcpy(mail_server_ip, w2);
|
||||
} else if(strcmpi(w1,"mail_server_port")==0){
|
||||
mail_server_port=atoi(w2);
|
||||
} else if(strcmpi(w1,"mail_server_id")==0){
|
||||
strcpy(mail_server_id, w2);
|
||||
} else if(strcmpi(w1,"mail_server_pw")==0){
|
||||
strcpy(mail_server_pw, w2);
|
||||
} else if(strcmpi(w1,"mail_server_db")==0){
|
||||
strcpy(mail_server_db, w2);
|
||||
} else if(strcmpi(w1,"mail_db")==0) {
|
||||
strcpy(mail_db, w2);
|
||||
#endif
|
||||
//support the import command, just like any other config
|
||||
} else if(strcmpi(w1,"import")==0){
|
||||
@ -2933,20 +2922,6 @@ int map_sql_init(void)
|
||||
if ( SQL_ERROR == Sql_SetEncoding(mmysql_handle, default_codepage) )
|
||||
Sql_ShowDebug(mmysql_handle);
|
||||
|
||||
if(mail_server_enable)
|
||||
{
|
||||
// mail system
|
||||
mail_handle = Sql_Malloc();
|
||||
|
||||
ShowInfo("Connecting to the Mail DB Server....\n");
|
||||
if( SQL_ERROR == Sql_Connect(mail_handle, mail_server_id, mail_server_pw, mail_server_ip, mail_server_port, mail_server_db) )
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if( strlen(default_codepage) > 0 )
|
||||
if ( SQL_ERROR == Sql_SetEncoding(mail_handle, default_codepage) )
|
||||
Sql_ShowDebug(mail_handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2963,13 +2938,6 @@ int map_sql_close(void)
|
||||
logmysql_handle = NULL;
|
||||
}
|
||||
|
||||
if(mail_server_enable)
|
||||
{
|
||||
ShowStatus("Close Mail DB Connection....\n");
|
||||
Sql_Free(mail_handle);
|
||||
mail_handle = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2999,8 +2967,6 @@ int map_sql_ping(int tid, unsigned int tick, int id, int data)
|
||||
Sql_Ping(mmysql_handle);
|
||||
if (log_config.sql_logs)
|
||||
Sql_Ping(logmysql_handle);
|
||||
if(mail_server_enable)
|
||||
Sql_Ping(mail_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3382,9 +3348,6 @@ int do_init(int argc, char *argv[])
|
||||
do_init_npc();
|
||||
do_init_unit();
|
||||
#ifndef TXT_ONLY /* mail system [Valaris] */
|
||||
if(mail_server_enable)
|
||||
do_init_mail();
|
||||
|
||||
if (log_config.sql_logs)
|
||||
log_sql_init();
|
||||
|
||||
|
@ -633,6 +633,7 @@ struct map_session_data {
|
||||
unsigned int canlog_tick;
|
||||
unsigned int canuseitem_tick; // [Skotlex]
|
||||
unsigned int cantalk_tick;
|
||||
unsigned int cansendmail_tick; // [Mail System Flood Protection]
|
||||
|
||||
short weapontype1,weapontype2;
|
||||
short disguise; // [Valaris]
|
||||
@ -799,15 +800,16 @@ struct map_session_data {
|
||||
|
||||
char fakename[NAME_LENGTH]; // fake names [Valaris]
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
int mail_counter; // mail counter for mail system (antiflood protection)
|
||||
#endif
|
||||
|
||||
int duel_group; // duel vars [LuzZza]
|
||||
int duel_invite;
|
||||
|
||||
char away_message[128]; // [LuzZza]
|
||||
|
||||
// Mail System [Zephyrus]
|
||||
struct {
|
||||
int index, amount, zeny;
|
||||
struct mail_data inbox;
|
||||
} mail;
|
||||
};
|
||||
|
||||
struct {
|
||||
@ -1342,6 +1344,7 @@ struct map_session_data** map_getallusers(int *users);
|
||||
void map_foreachpc(int (*func)(DBKey,void*,va_list),...);
|
||||
int map_foreachiddb(int (*)(DBKey,void*,va_list),...);
|
||||
struct map_session_data * map_nick2sd(const char*);
|
||||
struct map_session_data * map_nick2sd_nocase(const char *);
|
||||
|
||||
// ‚»‚Ì‘¼
|
||||
int map_check_dir(int s_dir,int t_dir);
|
||||
@ -1412,18 +1415,15 @@ extern char main_chat_nick[16];
|
||||
#include "../common/sql.h"
|
||||
|
||||
extern int db_use_sqldbs;
|
||||
extern int mail_server_enable;
|
||||
|
||||
extern Sql* mmysql_handle;
|
||||
extern Sql* logmysql_handle;
|
||||
extern Sql* mail_handle;
|
||||
|
||||
extern char item_db_db[32];
|
||||
extern char item_db2_db[32];
|
||||
extern char mob_db_db[32];
|
||||
extern char mob_db2_db[32];
|
||||
extern char char_db[32];
|
||||
extern char mail_db[32];
|
||||
|
||||
#endif /* not TXT_ONLY */
|
||||
|
||||
|
10
src/map/pc.c
10
src/map/pc.c
@ -633,6 +633,7 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
|
||||
|
||||
sd->canuseitem_tick = tick;
|
||||
sd->cantalk_tick = tick;
|
||||
sd->cansendmail_tick = tick;
|
||||
|
||||
for(i = 0; i < MAX_SKILL_LEVEL; i++)
|
||||
sd->spirit_timer[i] = -1;
|
||||
@ -743,11 +744,6 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
|
||||
clif_displaymessage(sd->fd, motd_text[i]);
|
||||
}
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
if(mail_server_enable)
|
||||
mail_check(sd,0); // check mail at login [Valaris]
|
||||
#endif
|
||||
|
||||
// message of the limited time of the account
|
||||
if (connect_until_time != 0) { // don't display if it's unlimited or unknow value
|
||||
char tmpstr[1024];
|
||||
@ -886,7 +882,9 @@ int pc_reg_received(struct map_session_data *sd)
|
||||
|
||||
status_calc_pc(sd,1);
|
||||
chrif_scdata_request(sd->status.account_id, sd->status.char_id);
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
|
||||
#endif
|
||||
if (!sd->state.connect_new && sd->fd)
|
||||
{ //Character already loaded map! Gotta trigger LoadEndAck manually.
|
||||
sd->state.connect_new = 1;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "unit.h"
|
||||
#include "irc.h"
|
||||
#include "pet.h"
|
||||
#include "mail.h"
|
||||
#include "script.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@ -4052,6 +4053,10 @@ BUILDIN_FUNC(getmonsterinfo); // [Lupus]
|
||||
BUILDIN_FUNC(checkvending); // check vending [Nab4]
|
||||
BUILDIN_FUNC(checkchatting); // check chatting [Marka]
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
BUILDIN_FUNC(openmail); // [Mail System]
|
||||
#endif
|
||||
|
||||
#ifdef PCRE_SUPPORT
|
||||
BUILDIN_FUNC(defpattern); // MouseJstr
|
||||
BUILDIN_FUNC(activatepset); // MouseJstr
|
||||
@ -4390,6 +4395,9 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(roclass,"i*"), //[Skotlex]
|
||||
BUILDIN_DEF(checkvending,"*"),
|
||||
BUILDIN_DEF(checkchatting,"*"),
|
||||
#ifndef TXT_ONLY
|
||||
BUILDIN_DEF(openmail,""),
|
||||
#endif
|
||||
{NULL,NULL,NULL},
|
||||
};
|
||||
|
||||
@ -13446,3 +13454,11 @@ BUILDIN_FUNC(warpportal)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef TXT_ONLY
|
||||
BUILDIN_FUNC(openmail)
|
||||
{
|
||||
mail_openmail(script_rid2sd(st));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Version="8,00"
|
||||
Name="char-server_sql"
|
||||
ProjectGUID="{D356871D-58E1-450B-967A-E4E9646175AF}"
|
||||
RootNamespace="char-server_sql"
|
||||
@ -361,6 +361,14 @@
|
||||
RelativePath="..\src\char_sql\int_homun.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\char_sql\int_mail.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\char_sql\int_mail.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\char_sql\int_party.c"
|
||||
>
|
||||
|
Loading…
x
Reference in New Issue
Block a user