diff options
Diffstat (limited to 'src/char')
-rw-r--r-- | src/char/HPMchar.c | 1 | ||||
-rw-r--r-- | src/char/Makefile.in | 4 | ||||
-rw-r--r-- | src/char/char.c | 20 | ||||
-rw-r--r-- | src/char/int_clan.c | 181 | ||||
-rw-r--r-- | src/char/int_clan.h | 39 | ||||
-rw-r--r-- | src/char/int_rodex.c | 74 | ||||
-rw-r--r-- | src/char/inter.c | 7 | ||||
-rw-r--r-- | src/char/mapif.c | 8 | ||||
-rw-r--r-- | src/char/mapif.h | 5 | ||||
-rw-r--r-- | src/char/pincode.c | 17 |
10 files changed, 314 insertions, 42 deletions
diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c index 3a74f443d..43a94604d 100644 --- a/src/char/HPMchar.c +++ b/src/char/HPMchar.c @@ -28,6 +28,7 @@ #include "char/geoip.h" #include "char/inter.h" #include "char/int_auction.h" +#include "char/int_clan.h" #include "char/int_elemental.h" #include "char/int_guild.h" #include "char/int_homun.h" diff --git a/src/char/Makefile.in b/src/char/Makefile.in index 1a7d067a4..fed7ec030 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -40,11 +40,11 @@ MT19937AR_D = $(THIRDPARTY_D)/mt19937ar MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o MT19937AR_H = $(MT19937AR_D)/mt19937ar.h -CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_auction.c int_elemental.c int_guild.c \ +CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_auction.c int_clan.c int_elemental.c int_guild.c \ int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \ int_quest.c int_rodex.c int_storage.c pincode.c CHAR_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(CHAR_C))) -CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_auction.h int_elemental.h int_guild.h \ +CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_auction.h int_clan.h int_elemental.h int_guild.h \ int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \ int_quest.h int_rodex.h int_storage.h pincode.h CHAR_PH = diff --git a/src/char/char.c b/src/char/char.c index c3fcd9e0a..0069e7f1d 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -26,6 +26,7 @@ #include "char/HPMchar.h" #include "char/geoip.h" #include "char/int_auction.h" +#include "char/int_clan.h" #include "char/int_elemental.h" #include "char/int_guild.h" #include "char/int_homun.h" @@ -465,7 +466,8 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) (p->look.head_mid != cp->look.head_mid) || (p->look.head_bottom != cp->look.head_bottom) || (p->delete_date != cp->delete_date) || (p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->look.robe != cp->look.robe) || (p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font) || - (p->uniqueitem_counter != cp->uniqueitem_counter) || (p->hotkey_rowshift != cp->hotkey_rowshift) + (p->uniqueitem_counter != cp->uniqueitem_counter) || (p->hotkey_rowshift != cp->hotkey_rowshift) || + (p->clan_id != cp->clan_id) || (p->last_login != cp->last_login) ) { //Save status unsigned int opt = 0; @@ -483,7 +485,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," "`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u'," - "`hotkey_rowshift`='%d'" + "`hotkey_rowshift`='%d',`clan_id`='%d',`last_login`='%"PRId64"'" " WHERE `account_id`='%d' AND `char_id` = '%d'", char_db, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, @@ -495,7 +497,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename, (unsigned long)p->delete_date, // FIXME: platform-dependent size p->look.robe,p->slotchange,opt,p->font,p->uniqueitem_counter, - p->hotkey_rowshift, + p->hotkey_rowshift,p->clan_id,p->last_login, p->account_id, p->char_id) ) { Sql_ShowDebug(inter->sql_handle); @@ -1173,7 +1175,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`," "`hair_color`,`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`,`slotchange`," - "`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`" + "`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`,`last_login`" " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db) || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1236,6 +1238,8 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_UINT32, &p->uniqueitem_counter, sizeof p->uniqueitem_counter, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 57, SQLDT_ENUM, &sex, sizeof sex, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 58, SQLDT_UCHAR, &p->hotkey_rowshift, sizeof p->hotkey_rowshift, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 59, SQLDT_INT, &p->clan_id, sizeof p->clan_id, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 60, SQLDT_INT64, &p->last_login, sizeof p->last_login, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); SQL->StmtFree(stmt); @@ -1612,7 +1616,7 @@ int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int case JOB_NOVICE: break; default: - return -2; // Char Creation Denied + return -2; // Char Creation Denied } //check other inputs @@ -3324,7 +3328,12 @@ void char_char_name_ack(int fd, int char_id) WFIFOHEAD(fd,30); WFIFOW(fd,0) = 0x2b09; WFIFOL(fd,2) = char_id; +#if !defined(PACKETVER_ZERO) && (PACKETVER >= 20180307 || (defined(PACKETVER_RE) && PACKETVER >= 20180221)) + if (chr->loadName(char_id, WFIFOP(fd,6)) == 0) + WFIFOL(fd, 6) = 0; +#else chr->loadName(char_id, WFIFOP(fd,6)); +#endif WFIFOSET(fd,30); } @@ -6424,6 +6433,7 @@ void char_load_defaults(void) loginif_defaults(); mapif_defaults(); inter_auction_defaults(); + inter_clan_defaults(); inter_elemental_defaults(); inter_guild_defaults(); inter_homunculus_defaults(); diff --git a/src/char/int_clan.c b/src/char/int_clan.c new file mode 100644 index 000000000..e68f6a655 --- /dev/null +++ b/src/char/int_clan.c @@ -0,0 +1,181 @@ +/** + * This file is part of Hercules. + * http://herc.ws - http://github.com/HerculesWS/Hercules + * + * Copyright (C) 2017 Hercules Dev Team + * + * Hercules is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#define HERCULES_CORE + +#include "config/core.h" // DBPATH +#include "int_clan.h" + +#include "char/char.h" +#include "char/inter.h" +#include "char/mapif.h" +#include "common/cbasetypes.h" +#include "common/memmgr.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/sql.h" +#include "common/strlib.h" +#include "common/timer.h" + +#include <stdio.h> +#include <stdlib.h> + +struct inter_clan_interface inter_clan_s; +struct inter_clan_interface *inter_clan; + +/** + * Kick offline members of a clan + * + * Perform the update on the DB to reset clan id to 0 + * of the members that are inactive for too long + * + * @param clan_id Id of the clan + * @param kick_interval Time needed to consider a player inactive and kick it + * @return 0 on failure, 1 on success + */ +int inter_clan_kick_inactive_members(int clan_id, int kick_interval) +{ + if (clan_id <= 0) { + ShowError("inter_clan_kick_inactive_members: Invalid clan id received '%d'\n", clan_id); + Assert_report(clan_id > 0); + return 0; + } else if (kick_interval <= 0) { + ShowError("inter_clan_kick_inactive_members: Invalid kick_interval received '%d'", kick_interval); + Assert_report(kick_interval > 0); + return 0; + } + + // Kick Inactive members + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET " + "`clan_id` = 0 WHERE `clan_id` = '%d' AND `online` = 0 AND `last_login` < %"PRId64, + char_db, clan_id, (int64)(time(NULL) - kick_interval))) + { + Sql_ShowDebug(inter->sql_handle); + return 0; + } + + return 1; +} + +/** + * Count members of a clan + * + * @param clan_id Id of the clan + * @param kick_interval Time needed to consider a player inactive and ignore it on the count + */ +int inter_clan_count_members(int clan_id, int kick_interval) +{ + struct SqlStmt *stmt; + int count = 0; + + if (clan_id <= 0) { + ShowError("inter_clan_count_members: Invalid clan id received '%d'\n", clan_id); + Assert_report(clan_id > 0); + return 0; + } else if (kick_interval <= 0) { + ShowError("inter_clan_count_member: Invalid kick_interval received '%d'", kick_interval); + Assert_report(kick_interval > 0); + return 0; + } + + stmt = SQL->StmtMalloc(inter->sql_handle); + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return 0; + } + + // Count members + if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT COUNT(*) FROM `%s` WHERE `clan_id` = ? AND `last_login` >= %"PRId64, char_db, (int64)(time(NULL) - kick_interval)) + || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &clan_id, sizeof(clan_id)) + || SQL_ERROR == SQL->StmtExecute(stmt) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &count, sizeof(count), NULL, NULL) + ) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); + return 0; + } + + if (SQL->StmtNumRows(stmt) > 0 && SQL_SUCCESS != SQL->StmtNextRow(stmt)) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); + return 0; + } + + SQL->StmtFree(stmt); + return count; +} + +int mapif_parse_ClanMemberCount(int fd, int clan_id, int kick_interval) +{ + + WFIFOHEAD(fd, 10); + WFIFOW(fd, 0) = 0x3858; + WFIFOL(fd, 2) = clan_id; + WFIFOL(fd, 6) = inter_clan->count_members(clan_id, kick_interval); + WFIFOSET(fd, 10); + return 0; +} + +int mapif_parse_ClanMemberKick(int fd, int clan_id, int kick_interval) +{ + int count = 0; + + if (inter_clan->kick_inactive_members(clan_id, kick_interval) == 1) + count = inter_clan->count_members(clan_id, kick_interval); + + WFIFOHEAD(fd, 10); + WFIFOW(fd, 0) = 0x3858; + WFIFOL(fd, 2) = clan_id; + WFIFOL(fd, 6) = count; + WFIFOSET(fd, 10); + return 0; +} + +// Communication from the map server +// - Can analyzed only one by one packet +// Data packet length that you set to inter.c +//- Shouldn't do checking and packet length, RFIFOSKIP is done by the caller +// Must Return +// 1 : ok +// 0 : error +int inter_clan_parse_frommap(int fd) +{ + RFIFOHEAD(fd); + + switch(RFIFOW(fd, 0)) { + case 0x3044: mapif->parse_ClanMemberCount(fd, RFIFOL(fd, 2), RFIFOL(fd, 6)); break; + case 0x3045: mapif->parse_ClanMemberKick(fd, RFIFOL(fd, 2), RFIFOL(fd, 6)); break; + + default: + return 0; + } + + return 1; +} + +void inter_clan_defaults(void) +{ + inter_clan = &inter_clan_s; + + inter_clan->kick_inactive_members = inter_clan_kick_inactive_members; + inter_clan->count_members = inter_clan_count_members; + inter_clan->parse_frommap = inter_clan_parse_frommap; +} diff --git a/src/char/int_clan.h b/src/char/int_clan.h new file mode 100644 index 000000000..e7b44ecd3 --- /dev/null +++ b/src/char/int_clan.h @@ -0,0 +1,39 @@ +/** + * This file is part of Hercules. + * http://herc.ws - http://github.com/HerculesWS/Hercules + * + * Copyright (C) 2017 Hercules Dev Team + * + * Hercules is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef CHAR_INT_CLAN_H +#define CHAR_INT_CLAN_H + +#include "common/mmo.h" + +/** + * inter clan Interface + **/ +struct inter_clan_interface { + int (*kick_inactive_members) (int clan_id, int kick_interval); + int (*count_members) (int clan_id, int kick_interval); + int (*parse_frommap) (int fd); +}; + +#ifdef HERCULES_CORE +void inter_clan_defaults(void); +#endif // HERCULES_CORE + +HPShared struct inter_clan_interface *inter_clan; +#endif /* CHAR_INT_CLAN_H */ diff --git a/src/char/int_rodex.c b/src/char/int_rodex.c index f5d036991..2001ddc43 100644 --- a/src/char/int_rodex.c +++ b/src/char/int_rodex.c @@ -55,7 +55,7 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 case RODEX_OPENTYPE_MAIL: if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`," - "`title`, `body`, `zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`" + "`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`" "FROM `%s` WHERE `expire_date` > '%d' AND `receiver_id` = '%d' AND `mail_id` > '%"PRId64"'" "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, mail_id) ) { @@ -68,7 +68,7 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 case RODEX_OPENTYPE_ACCOUNT: if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`," - "`title`, `body`, `zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`" + "`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`" "FROM `%s` WHERE " "`expire_date` > '%d' AND `receiver_accountid` = '%d' AND `mail_id` > '%"PRId64"'" "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), account_id, mail_id) @@ -82,8 +82,8 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 case RODEX_OPENTYPE_RETURN: if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`," - "`title`, `body`, `zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`" - "FROM `%s` WHERE (`sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d' AND `mail_id` > '%"PRId64"')" + "`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`" + "FROM `%s` WHERE (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d' AND `mail_id` > '%"PRId64"')" "ORDER BY `mail_id` ASC", rodex_db, char_id, (int)time(NULL), 2 * RODEX_EXPIRE, (int)time(NULL), mail_id) ) { SqlStmt_ShowDebug(stmt); @@ -95,9 +95,11 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 case RODEX_OPENTYPE_UNSET: if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`," - "`title`, `body`, `zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`" - "FROM `%s` WHERE `expire_date` > '%d' AND (`receiver_id` = '%d' or `receiver_accountid` = '%d') AND `mail_id` > '%"PRId64"'" - "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, account_id, mail_id) + "`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`" + "FROM `%s` WHERE " + "((`expire_date` > '%d' AND (`receiver_id` = '%d' OR `receiver_accountid` = '%d'))" + "OR (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d'))" + "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, account_id, char_id, (int)time(NULL), 2 * RODEX_EXPIRE, (int)time(NULL)) ) { SqlStmt_ShowDebug(stmt); SQL->StmtFree(stmt); @@ -118,9 +120,10 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT64, &msg.zeny, sizeof msg.zeny, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_UINT8, &msg.type, sizeof msg.type, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_BOOL, &msg.is_read, sizeof msg.is_read, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_INT, &msg.send_date, sizeof msg.send_date, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_INT, &msg.expire_date, sizeof msg.expire_date, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_INT, &msg.weight, sizeof msg.weight, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_BOOL, &msg.sender_read, sizeof msg.sender_read, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_INT, &msg.send_date, sizeof msg.send_date, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_INT, &msg.expire_date, sizeof msg.expire_date, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_INT, &msg.weight, sizeof msg.weight, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); SQL->StmtFree(stmt); @@ -201,10 +204,12 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 #if PACKETVER >= 20170419 if (opentype == RODEX_OPENTYPE_UNSET) { - if (msg.receiver_id != 0) - msg.opentype = RODEX_OPENTYPE_MAIL; - else + if (msg.receiver_id == 0) msg.opentype = RODEX_OPENTYPE_ACCOUNT; + else if (msg.expire_date < time(NULL)) + msg.opentype = RODEX_OPENTYPE_RETURN; + else + msg.opentype = RODEX_OPENTYPE_MAIL; } else { msg.opentype = opentype; } @@ -243,8 +248,8 @@ static bool inter_rodex_hasnew(int char_id, int account_id) if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT count(*) FROM `%s` WHERE (" "(`expire_date` > '%d' AND (`receiver_id` = '%d' OR `receiver_accountid` = '%d')) OR" - "(`sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d')" - ") AND (`is_read` = 0 OR (`type` > 0 AND `type` != 8))", + "(`sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d' AND `is_read` = 0)" // is_read is required in this line because of the OR in next condition + ") AND ((`is_read` = 0 AND `sender_read` = 0) OR (`type` > 0 AND `type` != 8))", rodex_db, (int)time(NULL), char_id, account_id, char_id, (int)time(NULL), 2 * RODEX_EXPIRE, (int)time(NULL)) ) { @@ -309,10 +314,10 @@ int64 inter_rodex_savemessage(struct rodex_message* msg) SQL->EscapeStringLen(inter->sql_handle, title, msg->title, strnlen(msg->title, RODEX_TITLE_LENGTH)); if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` (`sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`, `title`, `body`," - "`zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`) VALUES " - "('%s', '%d', '%s', '%d', '%d', '%s', '%s', '%"PRId64"', '%d', '%d', '%d', '%d', '%d')", + "`zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`) VALUES " + "('%s', '%d', '%s', '%d', '%d', '%s', '%s', '%"PRId64"', '%d', '%d', '%d', '%d', '%d', '%d')", rodex_db, sender_name, msg->sender_id, receiver_name, msg->receiver_id, msg->receiver_accountid, - title, body, msg->zeny, msg->type, msg->is_read == true ? 1 : 0, msg->send_date, msg->expire_date, msg->weight)) { + title, body, msg->zeny, msg->type, msg->is_read == true ? 1 : 0, msg->sender_read == true ? 1 : 0, msg->send_date, msg->expire_date, msg->weight)) { Sql_ShowDebug(inter->sql_handle); return 0; } @@ -344,29 +349,31 @@ int64 inter_rodex_savemessage(struct rodex_message* msg) /*========================================== * Inbox Request *------------------------------------------*/ -void mapif_rodex_sendinbox(int fd, int char_id, int8 opentype, int8 flag, int count, struct rodex_maillist *mails) +void mapif_rodex_sendinbox(int fd, int char_id, int8 opentype, int8 flag, int count, int64 mail_id, struct rodex_maillist *mails) { - int per_packet = (UINT16_MAX - 15) / sizeof(struct rodex_message); + int per_packet = (UINT16_MAX - 24) / sizeof(struct rodex_message); int sent = 0; + bool is_first = true; nullpo_retv(mails); Assert_retv(char_id > 0); Assert_retv(count >= 0); + Assert_retv(mail_id >= 0); do { - int i = 15, j, size, limit; + int i = 24, j, size, limit; + int to_send = count - sent; bool is_last = true; - if (count <= per_packet) { - size = count * sizeof(struct rodex_message) + 15; - limit = count; + if (to_send <= per_packet) { + size = to_send * sizeof(struct rodex_message) + 24; + limit = to_send; is_last = true; } else { - int to_send = count - sent; limit = min(to_send, per_packet); if (limit != to_send) { is_last = false; } - size = limit * sizeof(struct rodex_message) + 15; + size = limit * sizeof(struct rodex_message) + 24; } WFIFOHEAD(fd, size); @@ -376,11 +383,15 @@ void mapif_rodex_sendinbox(int fd, int char_id, int8 opentype, int8 flag, int co WFIFOB(fd, 8) = opentype; WFIFOB(fd, 9) = flag; WFIFOB(fd, 10) = is_last; - WFIFOL(fd, 11) = count; + WFIFOB(fd, 11) = is_first; + WFIFOL(fd, 12) = limit; + WFIFOQ(fd, 16) = mail_id; for (j = 0; j < limit; ++j, ++sent, i += sizeof(struct rodex_message)) { memcpy(WFIFOP(fd, i), &VECTOR_INDEX(*mails, sent), sizeof(struct rodex_message)); } WFIFOSET(fd, size); + + is_first = false; } while (sent < count); } @@ -399,7 +410,7 @@ void mapif_parse_rodex_requestinbox(int fd) count = inter_rodex->fromsql(char_id, account_id, opentype, 0, &mails); else count = inter_rodex->fromsql(char_id, account_id, opentype, mail_id, &mails); - mapif->rodex_sendinbox(fd, char_id, opentype, flag, count, &mails); + mapif->rodex_sendinbox(fd, char_id, opentype, flag, count, mail_id, &mails); VECTOR_CLEAR(mails); } @@ -439,7 +450,7 @@ void mapif_parse_rodex_updatemail(int fd) int8 flag = RFIFOB(fd, 10); Assert_retv(mail_id > 0); - Assert_retv(flag >= 0 && flag <= 3); + Assert_retv(flag >= 0 && flag <= 4); switch (flag) { case 0: // Read @@ -465,6 +476,11 @@ void mapif_parse_rodex_updatemail(int fd) if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_item_db, mail_id)) Sql_ShowDebug(inter->sql_handle); break; + + case 4: // Sender Read + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `sender_read` = 1 WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id)) + Sql_ShowDebug(inter->sql_handle); + break; } } diff --git a/src/char/inter.c b/src/char/inter.c index 557ee5313..b095a046d 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -25,6 +25,7 @@ #include "char/char.h" #include "char/geoip.h" #include "char/int_auction.h" +#include "char/int_clan.h" #include "char/int_elemental.h" #include "char/int_guild.h" #include "char/int_homun.h" @@ -72,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- Account Storage [Smokexyz] -1,10,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, // 3020- Party -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030- - -1, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040- + -1, 9, 0, 0, 10,10, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040- Clan System(3044-3045) -1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus], Item Bound [Mhalicot] 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish] -1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil] @@ -526,12 +527,15 @@ void mapif_parse_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int acc inter->msg_to_fd(map_fd, u_fd, u_aid, "-- Account %d --", account_id); inter->msg_to_fd(map_fd, u_fd, u_aid, "User: %s | GM Group: %d | State: %d", userid, group_id, state); +// enable this if you really know what you doing. +#if 0 if (*user_pass != '\0') { /* password is only received if your gm level is greater than the one you're searching for */ if (pin_code && *pin_code != '\0') inter->msg_to_fd(map_fd, u_fd, u_aid, "Password: %s (PIN:%s)", user_pass, pin_code); else inter->msg_to_fd(map_fd, u_fd, u_aid, "Password: %s", user_pass ); } +#endif inter->msg_to_fd(map_fd, u_fd, u_aid, "Account e-mail: %s | Birthdate: %s", email, birthdate); inter->msg_to_fd(map_fd, u_fd, u_aid, "Last IP: %s (%s)", last_ip, geoip->getcountry(sockt->str2ip(last_ip))); @@ -1420,6 +1424,7 @@ int inter_parse_frommap(int fd) || inter_auction->parse_frommap(fd) || inter_quest->parse_frommap(fd) || inter_rodex->parse_frommap(fd) + || inter_clan->parse_frommap(fd) ) break; else diff --git a/src/char/mapif.c b/src/char/mapif.c index 9fccd691b..f80e38fe7 100644 --- a/src/char/mapif.c +++ b/src/char/mapif.c @@ -185,7 +185,7 @@ void mapif_send_quests(int fd, int char_id, struct quest *tmp_questlog, int num_ int mapif_parse_quest_load(int fd); /* RoDEX */ int mapif_parse_rodex_requestinbox(int fd); -void mapif_rodex_sendinbox(int fd, int char_id, int8 opentype, int8 flag, int count, struct rodex_maillist *mails); +void mapif_rodex_sendinbox(int fd, int char_id, int8 opentype, int8 flag, int count, int64 mail_id, struct rodex_maillist *mails); int mapif_parse_rodex_checkhasnew(int fd); void mapif_rodex_sendhasnew(int fd, int char_id, bool has_new); int mapif_parse_rodex_updatemail(int fd); @@ -221,6 +221,9 @@ int mapif_parse_Registry(int fd); int mapif_parse_RegistryRequest(int fd); void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, const char *const name); int mapif_parse_NameChangeRequest(int fd); +// Clan System +int mapif_parse_ClanMemberKick(int fd, int clan_id, int kick_interval); +int mapif_parse_ClanMemberCount(int fd, int clan_id, int kick_interval); struct mapif_interface mapif_s; struct mapif_interface *mapif; @@ -411,4 +414,7 @@ void mapif_defaults(void) { mapif->parse_RegistryRequest = mapif_parse_RegistryRequest; mapif->namechange_ack = mapif_namechange_ack; mapif->parse_NameChangeRequest = mapif_parse_NameChangeRequest; + /* Clan System */ + mapif->parse_ClanMemberKick = mapif_parse_ClanMemberKick; + mapif->parse_ClanMemberCount = mapif_parse_ClanMemberCount; } diff --git a/src/char/mapif.h b/src/char/mapif.h index a78940ba2..7fc79f661 100644 --- a/src/char/mapif.h +++ b/src/char/mapif.h @@ -177,7 +177,7 @@ struct mapif_interface { void (*send_quests) (int fd, int char_id, struct quest *tmp_questlog, int num_quests); int (*parse_quest_load) (int fd); int(*parse_rodex_requestinbox) (int fd); - void(*rodex_sendinbox) (int fd, int char_id, int8 opentype, int8 flag, int count, struct rodex_maillist *mails); + void(*rodex_sendinbox) (int fd, int char_id, int8 opentype, int8 flag, int count, int64 mail_id, struct rodex_maillist *mails); int(*parse_rodex_checkhasnew) (int fd); void(*rodex_sendhasnew) (int fd, int char_id, bool has_new); int(*parse_rodex_updatemail) (int fd); @@ -213,6 +213,9 @@ struct mapif_interface { int (*parse_RegistryRequest) (int fd); void (*namechange_ack) (int fd, int account_id, int char_id, int type, int flag, const char *name); int (*parse_NameChangeRequest) (int fd); + // Clan System + int (*parse_ClanMemberKick) (int fd, int clan_id, int kick_interval); + int (*parse_ClanMemberCount) (int fd, int clan_id, int kick_interval); }; #ifdef HERCULES_CORE diff --git a/src/char/pincode.c b/src/char/pincode.c index fc1a4c037..bca1b4394 100644 --- a/src/char/pincode.c +++ b/src/char/pincode.c @@ -68,6 +68,8 @@ void pincode_check(int fd, struct char_session_data* sd) { char pin[5] = "\0\0\0\0"; nullpo_retv(sd); + if (strlen(sd->pincode) != 4) + return; safestrncpy(pin, RFIFOP(fd, 6), sizeof(pin)); pincode->decrypt(sd->pincode_seed, pin); if( pincode->compare( fd, sd, pin ) ){ @@ -87,7 +89,9 @@ int pincode_compare(int fd, struct char_session_data* sd, char* pin) { } else { pincode->sendstate( fd, sd, PINCODE_WRONG ); if( pincode->maxtry && ++sd->pincode_try >= pincode->maxtry ){ - pincode->error( sd->account_id ); + pincode->error(sd->account_id); + chr->authfail_fd(fd, 0); + chr->disconnect_player(sd->account_id); } return 0; } @@ -97,6 +101,8 @@ void pincode_change(int fd, struct char_session_data* sd) { char oldpin[5] = "\0\0\0\0", newpin[5] = "\0\0\0\0"; nullpo_retv(sd); + if (strlen(sd->pincode) != 4) + return; safestrncpy(oldpin, RFIFOP(fd,6), sizeof(oldpin)); pincode->decrypt(sd->pincode_seed,oldpin); if( !pincode->compare( fd, sd, oldpin ) ) @@ -113,6 +119,8 @@ void pincode_setnew(int fd, struct char_session_data* sd) { char newpin[5] = "\0\0\0\0"; nullpo_retv(sd); + if (strlen(sd->pincode) == 4) + return; safestrncpy(newpin, RFIFOP(fd,6), sizeof(newpin)); pincode->decrypt(sd->pincode_seed,newpin); pincode->update( sd->account_id, newpin ); @@ -172,8 +180,11 @@ void pincode_decrypt(unsigned int userSeed, char* pin) { } } - for( i = 0; i < 4; i++ ){ - pin[i] = tab[pin[i] - '0']; + for (i = 0; i < 4; i++ ) { + if (pin[i] < '0' || pin[i] > '9') + pin[i] = '0'; + else + pin[i] = tab[pin[i] - '0']; } sprintf(pin, "%d%d%d%d", pin[0], pin[1], pin[2], pin[3]); |