
- Abstraction for the sql code (sql.c/h). - New configure script and makefiles. - Restored txt zeny logging code. (r10814) - Rewrote mapserver's sql code - itemdb, mobdb, mapreg, logs. (r10814) - Fixed a precedence issue (&& and ) in char_sql/char.c. (r10833) - Improved db reading code a bit for consistency. (r11077) - Added separate atcommand for mail deletion. (r11077) - Corrected a few messages that said "new" instead of "unread". (r11077) - Broadcast (*) messages now use "*" as the target's name (not ""). (r11077) - Moved StringBuf code from utils.c/h to strlib.c/h. (r11084 r11117) - Some misc login server cleanups (reformatting etc). (r11136) - Corrected/modified some header entries. (r11141 r11147 11148) - Adjusted VS project files. (r11147) - Adjusted the way the sql charserver does item saving. (r11192) - Corrected usage of reserved keyword 'friend' in mmo.h. (r11192) git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11245 54d463be-8e91-2dee-dedb-b68131a5f0ec
370 lines
10 KiB
C
370 lines
10 KiB
C
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
|
// For more information, see LICENCE in the main folder
|
|
|
|
#ifndef TXT_ONLY
|
|
|
|
#include "../common/strlib.h"
|
|
#include "../common/socket.h"
|
|
#include "../common/timer.h"
|
|
#include "../common/nullpo.h"
|
|
#include "../common/showmsg.h"
|
|
|
|
#include "map.h"
|
|
#include "clif.h"
|
|
#include "chrif.h"
|
|
#include "intif.h"
|
|
#include "atcommand.h"
|
|
#include "pc.h"
|
|
#include "mail.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
int MAIL_CHECK_TIME = 120000;
|
|
int mail_timer;
|
|
|
|
/// type: 0 - mail check at login, silent if there aren't any new messages
|
|
/// 1 - @checkmail, just print the number of messages
|
|
/// 2 - @listmail, shows both read and unread messages
|
|
/// 3 - @listnewmail, shows only unread messages
|
|
int mail_check(struct map_session_data* sd, int type)
|
|
{
|
|
int i = 0, new_ = 0, priority = 0; // counters
|
|
char message[80];
|
|
|
|
nullpo_retr (0, sd);
|
|
|
|
// retrieve all existing messages for this player
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` FROM `%s` WHERE `to_account_id` = %d ORDER by `message_id`", mail_db, sd->status.account_id) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
if( Sql_NumRows(mail_handle) == 0)
|
|
{
|
|
clif_displaymessage(sd->fd, msg_txt(516)); // "You have no messages."
|
|
Sql_FreeResult(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
|
|
{
|
|
char* data;
|
|
int message_id;
|
|
int to_account_id;
|
|
char from_char_name[NAME_LENGTH];
|
|
bool read_flag, priority_flag, check_flag;
|
|
|
|
Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
|
|
Sql_GetData(mail_handle, 1, &data, NULL); to_account_id = atoi(data);
|
|
Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name));
|
|
Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data);
|
|
Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data);
|
|
Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data);
|
|
|
|
i++;
|
|
|
|
if( !check_flag )
|
|
{
|
|
// mark this message as checked
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
|
|
Sql_ShowDebug(mail_handle);
|
|
}
|
|
|
|
if( !read_flag )
|
|
{
|
|
new_++;
|
|
if(priority_flag)
|
|
priority++;
|
|
|
|
if( type == 2 || type == 3 )
|
|
{
|
|
if( priority_flag )
|
|
{
|
|
snprintf(message, 80, msg_txt(511), i, from_char_name);
|
|
clif_displaymessage(sd->fd, message); // "%d - From : %s (New - Priority)"
|
|
}
|
|
else
|
|
{
|
|
snprintf(message, 80, msg_txt(512), i, from_char_name);
|
|
clif_displaymessage(sd->fd, message); // "%d - From : %s (New)"
|
|
}
|
|
}
|
|
}
|
|
else if( type == 2 )
|
|
{
|
|
snprintf(message, 80, msg_txt(513), i, from_char_name);
|
|
clif_displaymessage(sd->fd, message); // "%d - From : %s"
|
|
}
|
|
}
|
|
|
|
Sql_FreeResult(mail_handle);
|
|
|
|
if( new_ > 0 && (type == 0 || type == 1) )
|
|
{
|
|
sprintf(message, msg_txt(514), new_);
|
|
clif_displaymessage(sd->fd, message); // "You have %d unread messages."
|
|
if (priority > 0)
|
|
{
|
|
sprintf(message, msg_txt(515), priority);
|
|
clif_displaymessage(sd->fd, message); // "You have %d unread priority messages."
|
|
}
|
|
}
|
|
if( new_ == 0 && type != 0 )
|
|
{
|
|
clif_displaymessage(sd->fd, msg_txt(516)); // "You have no unread messages."
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// displays the selected message
|
|
int mail_read(struct map_session_data* sd, int index)
|
|
{
|
|
char* data;
|
|
int message_id;
|
|
char from_char_name[NAME_LENGTH];
|
|
char message[80];
|
|
bool read_flag, priority_flag, check_flag;
|
|
char output[100];
|
|
|
|
nullpo_retr(0, sd);
|
|
|
|
// 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);
|
|
return 0;
|
|
}
|
|
|
|
if( 0 == Sql_NumRows(mail_handle) )
|
|
{
|
|
clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found."
|
|
Sql_FreeResult(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
if( SQL_ERROR == Sql_NextRow(mail_handle) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
Sql_FreeResult(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
|
|
Sql_GetData(mail_handle, 1, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name));
|
|
Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(message, data, sizeof(message));
|
|
Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data);
|
|
Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data);
|
|
Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data);
|
|
|
|
Sql_FreeResult(mail_handle);
|
|
|
|
// mark mail as checked
|
|
if( !check_flag )
|
|
{
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
|
|
Sql_ShowDebug(mail_handle);
|
|
}
|
|
|
|
sprintf(output, msg_txt(518), from_char_name);
|
|
clif_displaymessage(sd->fd, output); // "Reading message from %s"
|
|
clif_displaymessage(sd->fd, message);
|
|
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `read_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// message deletion
|
|
int mail_delete(struct map_session_data* sd, int index)
|
|
{
|
|
char* data;
|
|
int message_id;
|
|
bool read_flag, priority_flag, check_flag;
|
|
|
|
nullpo_retr (0, sd);
|
|
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = %d ORDER by `message_id` LIMIT %d, 1", mail_db, sd->status.account_id, index-1) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
if( 0 == Sql_NumRows(mail_handle) )
|
|
{
|
|
clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found."
|
|
Sql_FreeResult(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
if( SQL_ERROR == Sql_NextRow(mail_handle) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
Sql_FreeResult(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data);
|
|
Sql_GetData(mail_handle, 1, &data, NULL); read_flag = (bool)atoi(data);
|
|
Sql_GetData(mail_handle, 2, &data, NULL); priority_flag = (bool)atoi(data);
|
|
Sql_GetData(mail_handle, 3, &data, NULL); check_flag = (bool)atoi(data);
|
|
|
|
Sql_FreeResult(mail_handle);
|
|
|
|
if( !read_flag && priority_flag )
|
|
{
|
|
clif_displaymessage(sd->fd,msg_txt(519)); // "Cannot delete unread priority mail."
|
|
return 0;
|
|
}
|
|
|
|
if( !check_flag )
|
|
{
|
|
clif_displaymessage(sd->fd,msg_txt(520)); // "You have received new mail, use @listmail before deleting."
|
|
return 0;
|
|
}
|
|
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "DELETE FROM `%s` WHERE `message_id` = %d", mail_db, message_id) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
clif_displaymessage(sd->fd,msg_txt(521)); // "Message deleted."
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// for sending normal and priority messages
|
|
int mail_send(struct map_session_data* sd, char* name, char* message, int flag)
|
|
{
|
|
SqlStmt* stmt;
|
|
|
|
nullpo_retr (0, sd);
|
|
|
|
if( pc_isGM(sd) < 80 && sd->mail_counter > 0 )
|
|
{
|
|
clif_displaymessage(sd->fd,msg_txt(522)); // "You must wait 10 minutes before sending another message"
|
|
return 0;
|
|
}
|
|
|
|
if( strcmp(name,"*") == 0 && pc_isGM(sd) < 80 )
|
|
{
|
|
clif_displaymessage(sd->fd, msg_txt(523)); // "Access Denied."
|
|
return 0;
|
|
}
|
|
|
|
if( strcmp(name,"*") == 0 )
|
|
{
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `account_id` FROM `%s` WHERE `account_id` != '%d' ORDER BY `account_id`", char_db, sd->status.account_id) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char name_[2*NAME_LENGTH];
|
|
Sql_EscapeString(mail_handle, name_, name);
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `account_id` FROM `%s` WHERE `name` = '%s'", char_db, name_) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if( 0 == Sql_NumRows(mail_handle) )
|
|
{
|
|
clif_displaymessage(sd->fd,msg_txt(524)); // "Character does not exist."
|
|
Sql_FreeResult(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
stmt = SqlStmt_Malloc(mail_handle);
|
|
SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`) VALUES (?, ?, '%d', ?, ?, '%d')", mail_db, sd->status.account_id, flag);
|
|
SqlStmt_BindParam(stmt, 1, SQLDT_STRING, name, strnlen(name, NAME_LENGTH));
|
|
SqlStmt_BindParam(stmt, 2, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH));
|
|
SqlStmt_BindParam(stmt, 3, SQLDT_STRING, message, strnlen(message, 80));
|
|
|
|
while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
|
|
{
|
|
int id;
|
|
char* data;
|
|
Sql_GetData(mail_handle, 0, &data, NULL); id = atoi(data);
|
|
SqlStmt_BindParam(stmt, 0, SQLDT_INT, &id, sizeof(id));
|
|
if( SQL_ERROR == SqlStmt_Execute(stmt) )
|
|
SqlStmt_ShowDebug(stmt);
|
|
}
|
|
Sql_FreeResult(mail_handle);
|
|
SqlStmt_Free(stmt);
|
|
|
|
if(pc_isGM(sd) < 80)
|
|
sd->mail_counter = 5;
|
|
|
|
clif_displaymessage(sd->fd,msg_txt(525)); // "Mail has been sent."
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// invoked every MAIL_CHECK_TIME ms, decreases the send blocking counter
|
|
static int mail_check_timer_sub(struct map_session_data* sd, va_list va)
|
|
{
|
|
if(sd->mail_counter > 0)
|
|
sd->mail_counter--;
|
|
return 0;
|
|
}
|
|
|
|
/// periodically checks for new messages and notifies about them
|
|
int mail_check_timer(int tid, unsigned int tick, int id, int data)
|
|
{
|
|
if(mail_timer != tid)
|
|
return 0;
|
|
|
|
mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0);
|
|
|
|
// fetch account ids of people who received new mail since the last iteration
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `to_account_id` FROM `%s` WHERE `read_flag` = '0' AND `check_flag` = '0'", mail_db) )
|
|
{
|
|
Sql_ShowDebug(mail_handle);
|
|
return 0;
|
|
}
|
|
|
|
while( SQL_SUCCESS == Sql_NextRow(mail_handle) )
|
|
{
|
|
char* id;
|
|
struct map_session_data* sd;
|
|
Sql_GetData(mail_handle, 0, &id, NULL);
|
|
if( (sd = map_id2sd(atoi(id))) != NULL )
|
|
clif_displaymessage(sd->fd, msg_txt(526)); // "You have new mail."
|
|
}
|
|
|
|
Sql_FreeResult(mail_handle);
|
|
|
|
// decrease the send-blocking counter
|
|
clif_foreachclient(mail_check_timer_sub);
|
|
|
|
// The 'check_flag' indicates whether the player was informed about the message.
|
|
// All online players were notified by the above code, and offline players will get the notice at next login.
|
|
// Therefore it is safe to simply set the flag to '1' for all existing mails.
|
|
if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `check_flag` = 0", mail_db) )
|
|
Sql_ShowDebug(mail_handle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int do_init_mail(void)
|
|
{
|
|
add_timer_func_list(mail_check_timer, "mail_check_timer");
|
|
mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|