- 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
|
2007/10/22
|
||||||
* Heat isn't supposed to consume SP when used against players [Playtester]
|
* Heat isn't supposed to consume SP when used against players [Playtester]
|
||||||
- please report if it still consumes SP in pvp
|
- 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
|
2007/10/21
|
||||||
* Fixed a small mistake in r11503 causing a fatal error&exit on unix
|
* 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]
|
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
|
0x0190,21,actionrequest,5:20
|
||||||
0x0216,6
|
0x0216,6
|
||||||
//Start mail system?
|
//Start mail system?
|
||||||
0x023f,2
|
0x023f,2,mailrefresh,0
|
||||||
0x0240,8
|
0x0240,8
|
||||||
0x0241,6
|
0x0241,6,mailread,2
|
||||||
0x0242,-1
|
0x0242,-1
|
||||||
0x0243,6
|
0x0243,6,maildelete,2
|
||||||
0x0244,6
|
0x0244,6,mailgetattach,2
|
||||||
0x0245,7
|
0x0245,7
|
||||||
//Start writing a mail?
|
//Start writing a mail?
|
||||||
0x0246,4
|
0x0246,4,mailwinopen,2
|
||||||
//Send Item/Zeny
|
//Send Item/Zeny
|
||||||
0x0247,8
|
0x0247,8,mailsetattach,2:4
|
||||||
//Message
|
//Message
|
||||||
0x0248,68
|
0x0248,68
|
||||||
//Delivered?
|
//Delivered?
|
||||||
@ -811,7 +811,7 @@ packet_ver: 19
|
|||||||
|
|
||||||
//2005-08-29aSakexe
|
//2005-08-29aSakexe
|
||||||
0x0240,-1
|
0x0240,-1
|
||||||
0x0248,-1
|
0x0248,-1,mailsend,2:4:28:68
|
||||||
0x0255,5
|
0x0255,5
|
||||||
0x0256,0
|
0x0256,0
|
||||||
0x0257,8
|
0x0257,8
|
||||||
@ -871,7 +871,7 @@ packet_ver: 19
|
|||||||
0x0274,8
|
0x0274,8
|
||||||
|
|
||||||
//2006-03-13aSakexe
|
//2006-03-13aSakexe
|
||||||
0x0273,30
|
0x0273,30,mailreturn,2:6
|
||||||
|
|
||||||
//2006-03-27aSakexe
|
//2006-03-27aSakexe
|
||||||
packet_ver: 20
|
packet_ver: 20
|
||||||
|
@ -1,12 +1,23 @@
|
|||||||
|
DROP TABLE IF EXISTS `mail`;
|
||||||
CREATE TABLE `mail` (
|
CREATE TABLE `mail` (
|
||||||
`message_id` int(11) NOT NULL auto_increment,
|
`id` bigint(20) unsigned NOT NULL auto_increment,
|
||||||
`to_account_id` int(11) NOT NULL default '0',
|
`send_name` tinytext NOT NULL DEFAULT '',
|
||||||
`to_char_name` varchar(24) NOT NULL default '',
|
`send_id` int(11) unsigned NOT NULL default '0',
|
||||||
`from_account_id` int(11) NOT NULL default '0',
|
`dest_name` tinytext NOT NULL DEFAULT '',
|
||||||
`from_char_name` varchar(24) NOT NULL default '',
|
`dest_id` int(11) unsigned NOT NULL default '0',
|
||||||
`message` varchar(80) NOT NULL default '',
|
`title` tinytext NOT NULL DEFAULT '',
|
||||||
`read_flag` tinyint(1) NOT NULL default '0',
|
`message` text NOT NULL DEFAULT '',
|
||||||
`priority` tinyint(1) NOT NULL default '0',
|
`time` int(11) unsigned NOT NULL default '0',
|
||||||
`check_flag` tinyint(1) NOT NULL default '0',
|
`read_flag` tinyint(1) unsigned NOT NULL default '0',
|
||||||
PRIMARY KEY (`message_id`)
|
`zeny` int(11) unsigned NOT NULL default '0',
|
||||||
) TYPE=MyISAM;
|
`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/strlib.h ../common/grfio.h \
|
||||||
../common/mapindex.h ../common/ers.h ../common/sql.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@
|
HAVE_MYSQL=@HAVE_MYSQL@
|
||||||
ifeq ($(HAVE_MYSQL),yes)
|
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_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_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_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 guild_storage_db[256] = "guild_storage";
|
||||||
char party_db[256] = "party";
|
char party_db[256] = "party";
|
||||||
char pet_db[256] = "pet";
|
char pet_db[256] = "pet";
|
||||||
|
char mail_db[256] = "mail"; // MAIL SYSTEM
|
||||||
char friend_db[256] = "friends";
|
char friend_db[256] = "friends";
|
||||||
char hotkey_db[256] = "hotkey";
|
char hotkey_db[256] = "hotkey";
|
||||||
|
|
||||||
@ -3447,6 +3448,8 @@ void sql_config_read(const char* cfgName)
|
|||||||
strcpy(party_db,w2);
|
strcpy(party_db,w2);
|
||||||
else if(!strcmpi(w1,"pet_db"))
|
else if(!strcmpi(w1,"pet_db"))
|
||||||
strcpy(pet_db,w2);
|
strcpy(pet_db,w2);
|
||||||
|
else if(!strcmpi(w1,"mail_db"))
|
||||||
|
strcpy(mail_db,w2);
|
||||||
else if(!strcmpi(w1,"friend_db"))
|
else if(!strcmpi(w1,"friend_db"))
|
||||||
strcpy(friend_db,w2);
|
strcpy(friend_db,w2);
|
||||||
else if(!strcmpi(w1,"hotkey_db"))
|
else if(!strcmpi(w1,"hotkey_db"))
|
||||||
|
@ -57,6 +57,7 @@ extern char guild_skill_db[256];
|
|||||||
extern char guild_storage_db[256];
|
extern char guild_storage_db[256];
|
||||||
extern char party_db[256];
|
extern char party_db[256];
|
||||||
extern char pet_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]
|
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_storage.h"
|
||||||
#include "int_pet.h"
|
#include "int_pet.h"
|
||||||
#include "int_homun.h"
|
#include "int_homun.h"
|
||||||
|
#include "int_mail.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -26,6 +27,7 @@
|
|||||||
|
|
||||||
Sql* sql_handle = NULL;
|
Sql* sql_handle = NULL;
|
||||||
Sql* lsql_handle = NULL;
|
Sql* lsql_handle = NULL;
|
||||||
|
Sql* mail_handle = NULL;
|
||||||
|
|
||||||
int char_server_port = 3306;
|
int char_server_port = 3306;
|
||||||
char char_server_ip[32] = "127.0.0.1";
|
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_pw[32] = "ragnarok";
|
||||||
char login_server_db[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
|
#ifndef TXT_SQL_CONVERT
|
||||||
|
|
||||||
static struct accreg *accreg_pt;
|
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-
|
-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-
|
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-
|
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, // 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, // 3860-
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3870-
|
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-
|
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,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-
|
-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, // 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, // 3060-
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3070-
|
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);
|
strcpy(login_server_db, w2);
|
||||||
ShowStatus ("set login_server_db : %s\n", 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
|
#ifndef TXT_SQL_CONVERT
|
||||||
else if(!strcmpi(w1,"party_share_level"))
|
else if(!strcmpi(w1,"party_share_level"))
|
||||||
party_share_level = atoi(w2);
|
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");
|
ShowInfo("Pinging SQL server to keep connection alive...\n");
|
||||||
Sql_Ping(sql_handle);
|
Sql_Ping(sql_handle);
|
||||||
|
Sql_Ping(mail_handle);
|
||||||
if( char_gm_read )
|
if( char_gm_read )
|
||||||
Sql_Ping(lsql_handle);
|
Sql_Ping(lsql_handle);
|
||||||
return 0;
|
return 0;
|
||||||
@ -358,6 +389,16 @@ int inter_init_sql(const char *file)
|
|||||||
Sql_Free(sql_handle);
|
Sql_Free(sql_handle);
|
||||||
exit(EXIT_FAILURE);
|
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
|
#ifndef TXT_SQL_CONVERT
|
||||||
else if (inter_sql_test()) {
|
else if (inter_sql_test()) {
|
||||||
ShowStatus("Connect Success! (Character Server)\n");
|
ShowStatus("Connect Success! (Character Server)\n");
|
||||||
@ -370,6 +411,7 @@ int inter_init_sql(const char *file)
|
|||||||
{
|
{
|
||||||
Sql_ShowDebug(lsql_handle);
|
Sql_ShowDebug(lsql_handle);
|
||||||
Sql_Free(lsql_handle);
|
Sql_Free(lsql_handle);
|
||||||
|
Sql_Free(mail_handle);
|
||||||
Sql_Free(sql_handle);
|
Sql_Free(sql_handle);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -396,6 +438,7 @@ int inter_init_sql(const char *file)
|
|||||||
inter_pet_sql_init();
|
inter_pet_sql_init();
|
||||||
inter_homunculus_sql_init(); // albator
|
inter_homunculus_sql_init(); // albator
|
||||||
inter_accreg_sql_init();
|
inter_accreg_sql_init();
|
||||||
|
inter_mail_sql_init();
|
||||||
|
|
||||||
sql_ping_init();
|
sql_ping_init();
|
||||||
#endif //TXT_SQL_CONVERT
|
#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);
|
ShowSQL ("Field `%s` not be found in `%s`. Consider updating your database!\n", fields[i], char_db);
|
||||||
if( lsql_handle )
|
if( lsql_handle )
|
||||||
Sql_Free(lsql_handle);
|
Sql_Free(lsql_handle);
|
||||||
|
Sql_Free(mail_handle);
|
||||||
Sql_Free(sql_handle);
|
Sql_Free(sql_handle);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -863,6 +907,7 @@ int inter_parse_frommap(int fd)
|
|||||||
|| inter_storage_parse_frommap(fd)
|
|| inter_storage_parse_frommap(fd)
|
||||||
|| inter_pet_parse_frommap(fd)
|
|| inter_pet_parse_frommap(fd)
|
||||||
|| inter_homunculus_parse_frommap(fd)
|
|| inter_homunculus_parse_frommap(fd)
|
||||||
|
|| inter_mail_parse_frommap(fd)
|
||||||
)
|
)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
|
@ -26,6 +26,7 @@ extern char inter_log_filename[1024];
|
|||||||
|
|
||||||
extern Sql* sql_handle;
|
extern Sql* sql_handle;
|
||||||
extern Sql* lsql_handle;
|
extern Sql* lsql_handle;
|
||||||
|
extern Sql* mail_handle;
|
||||||
|
|
||||||
extern int char_server_port;
|
extern int char_server_port;
|
||||||
extern char char_server_ip[32];
|
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_pw[32];
|
||||||
extern char login_db_server_db[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];
|
extern char main_chat_nick[16];
|
||||||
|
|
||||||
int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type);
|
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_BASE 6001
|
||||||
#define HM_CLASS_MAX (HM_CLASS_BASE+MAX_HOMUNCULUS_CLASS-1)
|
#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 {
|
struct item {
|
||||||
int id;
|
int id;
|
||||||
short nameid;
|
short nameid;
|
||||||
@ -236,6 +241,32 @@ struct mmo_charstatus {
|
|||||||
#endif
|
#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 {
|
struct registry {
|
||||||
int global_num;
|
int global_num;
|
||||||
struct global_reg global[GLOBAL_REG_NUM];
|
struct global_reg global[GLOBAL_REG_NUM];
|
||||||
|
@ -270,13 +270,7 @@ ACMD_FUNC(homshuffle); //[Skotlex]
|
|||||||
ACMD_FUNC(showmobs); //KarLaeda
|
ACMD_FUNC(showmobs); //KarLaeda
|
||||||
ACMD_FUNC(feelreset); //[HiddenDragon]
|
ACMD_FUNC(feelreset); //[HiddenDragon]
|
||||||
#ifndef TXT_ONLY
|
#ifndef TXT_ONLY
|
||||||
ACMD_FUNC(checkmail); // [Valaris]
|
ACMD_FUNC(mail); // [MAIL SYSTEM]
|
||||||
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(refreshonline); // [Valaris]
|
ACMD_FUNC(refreshonline); // [Valaris]
|
||||||
#endif
|
#endif
|
||||||
#ifdef DMALLOC
|
#ifdef DMALLOC
|
||||||
@ -574,13 +568,7 @@ static AtCommandInfo atcommand_info[] = {
|
|||||||
{ AtCommand_ShowMobs, "@showmobs", 10, atcommand_showmobs }, //KarLaeda
|
{ AtCommand_ShowMobs, "@showmobs", 10, atcommand_showmobs }, //KarLaeda
|
||||||
{ AtCommand_FeelReset, "@feelreset", 10, atcommand_feelreset }, //[HiddenDragon]
|
{ AtCommand_FeelReset, "@feelreset", 10, atcommand_feelreset }, //[HiddenDragon]
|
||||||
#ifndef TXT_ONLY // sql-only commands
|
#ifndef TXT_ONLY // sql-only commands
|
||||||
{ AtCommand_CheckMail, "@checkmail", 1, atcommand_listmail }, // [Valaris]
|
{ AtCommand_Mail, "@mail", 1, atcommand_mail }, // [Mail System]
|
||||||
{ 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_RefreshOnline, "@refreshonline", 99, atcommand_refreshonline }, // [Valaris]
|
{ AtCommand_RefreshOnline, "@refreshonline", 99, atcommand_refreshonline }, // [Valaris]
|
||||||
#endif
|
#endif
|
||||||
#ifdef DMALLOC
|
#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 */
|
#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)
|
nullpo_retr(0,sd);
|
||||||
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);
|
|
||||||
|
|
||||||
|
mail_openmail(sd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,13 +255,7 @@ enum AtCommandType {
|
|||||||
AtCommand_HappyHappyJoyJoy,
|
AtCommand_HappyHappyJoyJoy,
|
||||||
// SQL-only commands start
|
// SQL-only commands start
|
||||||
#ifndef TXT_ONLY
|
#ifndef TXT_ONLY
|
||||||
AtCommand_CheckMail, // [Valaris]
|
AtCommand_Mail, // [Mail System]
|
||||||
AtCommand_ListMail, // [Valaris]
|
|
||||||
AtCommand_ListNewMail, // [Valaris]
|
|
||||||
AtCommand_ReadMail, // [Valaris]
|
|
||||||
AtCommand_SendMail, // [Valaris]
|
|
||||||
AtCommand_DeleteMail, // [Valaris]
|
|
||||||
AtCommand_SendPriorityMail, // [Valaris]
|
|
||||||
AtCommand_RefreshOnline, // [Valaris]
|
AtCommand_RefreshOnline, // [Valaris]
|
||||||
// SQL-only commands end
|
// SQL-only commands end
|
||||||
#endif
|
#endif
|
||||||
|
423
src/map/clif.c
423
src/map/clif.c
@ -36,6 +36,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "irc.h"
|
#include "irc.h"
|
||||||
#include "clif.h"
|
#include "clif.h"
|
||||||
|
#include "mail.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -2500,7 +2501,7 @@ int clif_updatestatus(struct map_session_data *sd,int type)
|
|||||||
|
|
||||||
case SP_ZENY:
|
case SP_ZENY:
|
||||||
WFIFOW(fd,0)=0xb1;
|
WFIFOW(fd,0)=0xb1;
|
||||||
WFIFOL(fd,4)=sd->status.zeny;
|
WFIFOL(fd,4)=sd->status.zeny - sd->mail.zeny;
|
||||||
break;
|
break;
|
||||||
case SP_BASEEXP:
|
case SP_BASEEXP:
|
||||||
WFIFOW(fd,0)=0xb1;
|
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);
|
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
|
* ƒpƒPƒbƒgƒfƒoƒbƒO
|
||||||
*------------------------------------------*/
|
*------------------------------------------*/
|
||||||
@ -11551,10 +11955,10 @@ static int packetdb_readdb(void)
|
|||||||
//#0x0240
|
//#0x0240
|
||||||
-1, -1, -1, -1, -1, 3, 4, 8, -1, 3, 70, 4, 8, 12, 4, 10,
|
-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,
|
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,
|
6, 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, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
//#0x0280
|
//#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, 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,
|
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_StoragePassword,"storagepassword"},
|
||||||
{clif_parse_Hotkey,"hotkey"},
|
{clif_parse_Hotkey,"hotkey"},
|
||||||
{clif_parse_AutoRevive,"autorevive"},
|
{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}
|
{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_final_clif(void);
|
||||||
int do_init_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_ */
|
#endif /* _CLIF_H_ */
|
||||||
|
281
src/map/intif.c
281
src/map/intif.c
@ -18,6 +18,7 @@
|
|||||||
#include "pet.h"
|
#include "pet.h"
|
||||||
#include "atcommand.h"
|
#include "atcommand.h"
|
||||||
#include "mercenary.h" //albator
|
#include "mercenary.h" //albator
|
||||||
|
#include "mail.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdio.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
|
-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
|
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
|
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,
|
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;
|
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からの通信
|
// inter serverからの通信
|
||||||
// エラーがあれば0(false)を返すこと
|
// エラーがあれば0(false)を返すこと
|
||||||
@ -1528,6 +1798,15 @@ int intif_parse(int fd)
|
|||||||
case 0x3841: intif_parse_GuildCastleDataSave(fd); break;
|
case 0x3841: intif_parse_GuildCastleDataSave(fd); break;
|
||||||
case 0x3842: intif_parse_GuildCastleAllDataLoad(fd); break;
|
case 0x3842: intif_parse_GuildCastleAllDataLoad(fd); break;
|
||||||
case 0x3843: intif_parse_GuildMasterChanged(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 0x3880: intif_parse_CreatePet(fd); break;
|
||||||
case 0x3881: intif_parse_RecvPetData(fd); break;
|
case 0x3881: intif_parse_RecvPetData(fd); break;
|
||||||
case 0x3882: intif_parse_SavePetOk(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_requestsave(int account_id, struct s_homunculus* sh);
|
||||||
int intif_homunculus_requestdelete(int homun_id);
|
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);
|
int CheckForCharServer(void);
|
||||||
|
|
||||||
|
399
src/map/mail.c
399
src/map/mail.c
@ -3,365 +3,122 @@
|
|||||||
|
|
||||||
#ifndef TXT_ONLY
|
#ifndef TXT_ONLY
|
||||||
|
|
||||||
#include "../common/strlib.h"
|
|
||||||
#include "../common/socket.h"
|
|
||||||
#include "../common/timer.h"
|
|
||||||
#include "../common/nullpo.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 "mail.h"
|
||||||
|
#include "itemdb.h"
|
||||||
|
#include "clif.h"
|
||||||
|
#include "pc.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <time.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
time_t mail_calctimes(void)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int i = 0, new_ = 0, priority = 0; // counters
|
time_t temp = time(NULL);
|
||||||
char message[80];
|
return mktime(localtime(&temp));
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// displays the selected message
|
int mail_removeitem(struct map_session_data *sd, short flag)
|
||||||
int mail_read(struct map_session_data* sd, int index)
|
|
||||||
{
|
{
|
||||||
char* data;
|
nullpo_retr(0,sd);
|
||||||
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);
|
if( sd->mail.amount )
|
||||||
|
|
||||||
// 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) )
|
|
||||||
{
|
{
|
||||||
Sql_ShowDebug(mail_handle);
|
if (flag)
|
||||||
return 0;
|
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) )
|
sd->mail.index = 0;
|
||||||
{
|
sd->mail.amount = 0;
|
||||||
clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found."
|
return 1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// message deletion
|
int mail_removezeny(struct map_session_data *sd, short flag)
|
||||||
int mail_delete(struct map_session_data* sd, int index)
|
|
||||||
{
|
{
|
||||||
char* data;
|
nullpo_retr(0,sd);
|
||||||
int message_id;
|
|
||||||
bool read_flag, priority_flag, check_flag;
|
|
||||||
|
|
||||||
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) )
|
sd->mail.zeny = 0;
|
||||||
{
|
clif_updatestatus(sd, SP_ZENY);
|
||||||
Sql_ShowDebug(mail_handle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 0 == Sql_NumRows(mail_handle) )
|
return 1;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// for sending normal and priority messages
|
char mail_setitem(struct map_session_data *sd, int idx, int amount)
|
||||||
int mail_send(struct map_session_data* sd, char* name, char* message, int flag)
|
|
||||||
{
|
{
|
||||||
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 )
|
sd->mail.zeny = amount;
|
||||||
{
|
clif_updatestatus(sd, SP_ZENY);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
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];
|
if( sd->status.inventory[n].amount < sd->mail.amount )
|
||||||
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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item));
|
||||||
|
msg->item.amount = sd->mail.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( 0 == Sql_NumRows(mail_handle) )
|
msg->zeny = sd->mail.zeny;
|
||||||
{
|
|
||||||
clif_displaymessage(sd->fd,msg_txt(524)); // "Character does not exist."
|
|
||||||
Sql_FreeResult(mail_handle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = SqlStmt_Malloc(mail_handle);
|
return 1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// invoked every MAIL_CHECK_TIME ms, decreases the send blocking counter
|
int mail_openmail(struct map_session_data *sd)
|
||||||
static int mail_check_timer_sub(struct map_session_data* sd, va_list va)
|
|
||||||
{
|
{
|
||||||
if(sd->mail_counter > 0)
|
nullpo_retr(0,sd);
|
||||||
sd->mail_counter--;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// periodically checks for new messages and notifies about them
|
if( sd->state.finalsave == 1 || sd->state.storage_flag || sd->vender_id || sd->state.trading )
|
||||||
int mail_check_timer(int tid, unsigned int tick, int id, int data)
|
|
||||||
{
|
|
||||||
if(mail_timer != tid)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0);
|
clif_Mail_openmail(sd->fd);
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,14 @@
|
|||||||
#ifndef _MAIL_H_
|
#ifndef _MAIL_H_
|
||||||
#define _MAIL_H_
|
#define _MAIL_H_
|
||||||
|
|
||||||
int mail_check(struct map_session_data *sd, int type);
|
#include "../common/mmo.h"
|
||||||
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);
|
|
||||||
|
|
||||||
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_ */
|
#endif /* _MAIL_H_ */
|
||||||
|
@ -75,16 +75,6 @@ char log_db_pw[32] = "ragnarok";
|
|||||||
char log_db[32] = "log";
|
char log_db[32] = "log";
|
||||||
Sql* logmysql_handle;
|
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 */
|
#endif /* not TXT_ONLY */
|
||||||
|
|
||||||
int lowest_gm_level = 1;
|
int lowest_gm_level = 1;
|
||||||
@ -1857,6 +1847,21 @@ struct map_session_data * map_nick2sd(const char *nick)
|
|||||||
return NULL;
|
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番?の物を探す
|
* id番?の物を探す
|
||||||
* 一三bjectの場合は配列を引くのみ
|
* 一三bjectの場合は配列を引くのみ
|
||||||
@ -2888,22 +2893,6 @@ int inter_config_read(char *cfgName)
|
|||||||
strcpy(log_db_pw, w2);
|
strcpy(log_db_pw, w2);
|
||||||
} else if(strcmpi(w1,"log_db_port")==0) {
|
} else if(strcmpi(w1,"log_db_port")==0) {
|
||||||
log_db_port = atoi(w2);
|
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
|
#endif
|
||||||
//support the import command, just like any other config
|
//support the import command, just like any other config
|
||||||
} else if(strcmpi(w1,"import")==0){
|
} else if(strcmpi(w1,"import")==0){
|
||||||
@ -2933,20 +2922,6 @@ int map_sql_init(void)
|
|||||||
if ( SQL_ERROR == Sql_SetEncoding(mmysql_handle, default_codepage) )
|
if ( SQL_ERROR == Sql_SetEncoding(mmysql_handle, default_codepage) )
|
||||||
Sql_ShowDebug(mmysql_handle);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2963,13 +2938,6 @@ int map_sql_close(void)
|
|||||||
logmysql_handle = NULL;
|
logmysql_handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mail_server_enable)
|
|
||||||
{
|
|
||||||
ShowStatus("Close Mail DB Connection....\n");
|
|
||||||
Sql_Free(mail_handle);
|
|
||||||
mail_handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2999,8 +2967,6 @@ int map_sql_ping(int tid, unsigned int tick, int id, int data)
|
|||||||
Sql_Ping(mmysql_handle);
|
Sql_Ping(mmysql_handle);
|
||||||
if (log_config.sql_logs)
|
if (log_config.sql_logs)
|
||||||
Sql_Ping(logmysql_handle);
|
Sql_Ping(logmysql_handle);
|
||||||
if(mail_server_enable)
|
|
||||||
Sql_Ping(mail_handle);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3382,9 +3348,6 @@ int do_init(int argc, char *argv[])
|
|||||||
do_init_npc();
|
do_init_npc();
|
||||||
do_init_unit();
|
do_init_unit();
|
||||||
#ifndef TXT_ONLY /* mail system [Valaris] */
|
#ifndef TXT_ONLY /* mail system [Valaris] */
|
||||||
if(mail_server_enable)
|
|
||||||
do_init_mail();
|
|
||||||
|
|
||||||
if (log_config.sql_logs)
|
if (log_config.sql_logs)
|
||||||
log_sql_init();
|
log_sql_init();
|
||||||
|
|
||||||
|
@ -633,6 +633,7 @@ struct map_session_data {
|
|||||||
unsigned int canlog_tick;
|
unsigned int canlog_tick;
|
||||||
unsigned int canuseitem_tick; // [Skotlex]
|
unsigned int canuseitem_tick; // [Skotlex]
|
||||||
unsigned int cantalk_tick;
|
unsigned int cantalk_tick;
|
||||||
|
unsigned int cansendmail_tick; // [Mail System Flood Protection]
|
||||||
|
|
||||||
short weapontype1,weapontype2;
|
short weapontype1,weapontype2;
|
||||||
short disguise; // [Valaris]
|
short disguise; // [Valaris]
|
||||||
@ -799,15 +800,16 @@ struct map_session_data {
|
|||||||
|
|
||||||
char fakename[NAME_LENGTH]; // fake names [Valaris]
|
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_group; // duel vars [LuzZza]
|
||||||
int duel_invite;
|
int duel_invite;
|
||||||
|
|
||||||
char away_message[128]; // [LuzZza]
|
char away_message[128]; // [LuzZza]
|
||||||
|
|
||||||
|
// Mail System [Zephyrus]
|
||||||
|
struct {
|
||||||
|
int index, amount, zeny;
|
||||||
|
struct mail_data inbox;
|
||||||
|
} mail;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -1342,6 +1344,7 @@ struct map_session_data** map_getallusers(int *users);
|
|||||||
void map_foreachpc(int (*func)(DBKey,void*,va_list),...);
|
void map_foreachpc(int (*func)(DBKey,void*,va_list),...);
|
||||||
int map_foreachiddb(int (*)(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(const char*);
|
||||||
|
struct map_session_data * map_nick2sd_nocase(const char *);
|
||||||
|
|
||||||
// ‚»‚Ì‘¼
|
// ‚»‚Ì‘¼
|
||||||
int map_check_dir(int s_dir,int t_dir);
|
int map_check_dir(int s_dir,int t_dir);
|
||||||
@ -1412,18 +1415,15 @@ extern char main_chat_nick[16];
|
|||||||
#include "../common/sql.h"
|
#include "../common/sql.h"
|
||||||
|
|
||||||
extern int db_use_sqldbs;
|
extern int db_use_sqldbs;
|
||||||
extern int mail_server_enable;
|
|
||||||
|
|
||||||
extern Sql* mmysql_handle;
|
extern Sql* mmysql_handle;
|
||||||
extern Sql* logmysql_handle;
|
extern Sql* logmysql_handle;
|
||||||
extern Sql* mail_handle;
|
|
||||||
|
|
||||||
extern char item_db_db[32];
|
extern char item_db_db[32];
|
||||||
extern char item_db2_db[32];
|
extern char item_db2_db[32];
|
||||||
extern char mob_db_db[32];
|
extern char mob_db_db[32];
|
||||||
extern char mob_db2_db[32];
|
extern char mob_db2_db[32];
|
||||||
extern char char_db[32];
|
extern char char_db[32];
|
||||||
extern char mail_db[32];
|
|
||||||
|
|
||||||
#endif /* not TXT_ONLY */
|
#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->canuseitem_tick = tick;
|
||||||
sd->cantalk_tick = tick;
|
sd->cantalk_tick = tick;
|
||||||
|
sd->cansendmail_tick = tick;
|
||||||
|
|
||||||
for(i = 0; i < MAX_SKILL_LEVEL; i++)
|
for(i = 0; i < MAX_SKILL_LEVEL; i++)
|
||||||
sd->spirit_timer[i] = -1;
|
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]);
|
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
|
// message of the limited time of the account
|
||||||
if (connect_until_time != 0) { // don't display if it's unlimited or unknow value
|
if (connect_until_time != 0) { // don't display if it's unlimited or unknow value
|
||||||
char tmpstr[1024];
|
char tmpstr[1024];
|
||||||
@ -886,7 +882,9 @@ int pc_reg_received(struct map_session_data *sd)
|
|||||||
|
|
||||||
status_calc_pc(sd,1);
|
status_calc_pc(sd,1);
|
||||||
chrif_scdata_request(sd->status.account_id, sd->status.char_id);
|
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)
|
if (!sd->state.connect_new && sd->fd)
|
||||||
{ //Character already loaded map! Gotta trigger LoadEndAck manually.
|
{ //Character already loaded map! Gotta trigger LoadEndAck manually.
|
||||||
sd->state.connect_new = 1;
|
sd->state.connect_new = 1;
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "irc.h"
|
#include "irc.h"
|
||||||
#include "pet.h"
|
#include "pet.h"
|
||||||
|
#include "mail.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -4052,6 +4053,10 @@ BUILDIN_FUNC(getmonsterinfo); // [Lupus]
|
|||||||
BUILDIN_FUNC(checkvending); // check vending [Nab4]
|
BUILDIN_FUNC(checkvending); // check vending [Nab4]
|
||||||
BUILDIN_FUNC(checkchatting); // check chatting [Marka]
|
BUILDIN_FUNC(checkchatting); // check chatting [Marka]
|
||||||
|
|
||||||
|
#ifndef TXT_ONLY
|
||||||
|
BUILDIN_FUNC(openmail); // [Mail System]
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PCRE_SUPPORT
|
#ifdef PCRE_SUPPORT
|
||||||
BUILDIN_FUNC(defpattern); // MouseJstr
|
BUILDIN_FUNC(defpattern); // MouseJstr
|
||||||
BUILDIN_FUNC(activatepset); // MouseJstr
|
BUILDIN_FUNC(activatepset); // MouseJstr
|
||||||
@ -4390,6 +4395,9 @@ struct script_function buildin_func[] = {
|
|||||||
BUILDIN_DEF(roclass,"i*"), //[Skotlex]
|
BUILDIN_DEF(roclass,"i*"), //[Skotlex]
|
||||||
BUILDIN_DEF(checkvending,"*"),
|
BUILDIN_DEF(checkvending,"*"),
|
||||||
BUILDIN_DEF(checkchatting,"*"),
|
BUILDIN_DEF(checkchatting,"*"),
|
||||||
|
#ifndef TXT_ONLY
|
||||||
|
BUILDIN_DEF(openmail,""),
|
||||||
|
#endif
|
||||||
{NULL,NULL,NULL},
|
{NULL,NULL,NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13446,3 +13454,11 @@ BUILDIN_FUNC(warpportal)
|
|||||||
|
|
||||||
return 0;
|
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"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8.00"
|
Version="8,00"
|
||||||
Name="char-server_sql"
|
Name="char-server_sql"
|
||||||
ProjectGUID="{D356871D-58E1-450B-967A-E4E9646175AF}"
|
ProjectGUID="{D356871D-58E1-450B-967A-E4E9646175AF}"
|
||||||
RootNamespace="char-server_sql"
|
RootNamespace="char-server_sql"
|
||||||
@ -361,6 +361,14 @@
|
|||||||
RelativePath="..\src\char_sql\int_homun.h"
|
RelativePath="..\src\char_sql\int_homun.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\char_sql\int_mail.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\char_sql\int_mail.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\char_sql\int_party.c"
|
RelativePath="..\src\char_sql\int_party.c"
|
||||||
>
|
>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user