summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
Diffstat (limited to 'src/char')
-rw-r--r--src/char/HPMchar.c7
-rw-r--r--src/char/HPMchar.h2
-rw-r--r--src/char/Makefile.in14
-rw-r--r--src/char/char.c1802
-rw-r--r--src/char/char.h20
-rw-r--r--src/char/geoip.c66
-rw-r--r--src/char/geoip.h2
-rw-r--r--src/char/int_achievement.c252
-rw-r--r--src/char/int_achievement.h53
-rw-r--r--src/char/int_auction.c296
-rw-r--r--src/char/int_auction.h2
-rw-r--r--src/char/int_clan.c155
-rw-r--r--src/char/int_clan.h39
-rw-r--r--src/char/int_elemental.c80
-rw-r--r--src/char/int_elemental.h8
-rw-r--r--src/char/int_guild.c611
-rw-r--r--src/char/int_guild.h18
-rw-r--r--src/char/int_homun.c142
-rw-r--r--src/char/int_homun.h9
-rw-r--r--src/char/int_mail.c297
-rw-r--r--src/char/int_mail.h7
-rw-r--r--src/char/int_mercenary.c89
-rw-r--r--src/char/int_mercenary.h8
-rw-r--r--src/char/int_party.c292
-rw-r--r--src/char/int_party.h10
-rw-r--r--src/char/int_pet.c186
-rw-r--r--src/char/int_pet.h6
-rw-r--r--src/char/int_quest.c110
-rw-r--r--src/char/int_quest.h8
-rw-r--r--src/char/int_rodex.c432
-rw-r--r--src/char/int_rodex.h48
-rw-r--r--src/char/int_storage.c416
-rw-r--r--src/char/int_storage.h10
-rw-r--r--src/char/inter.c436
-rw-r--r--src/char/inter.h15
-rw-r--r--src/char/loginif.c32
-rw-r--r--src/char/loginif.h2
-rw-r--r--src/char/mapif.c2647
-rw-r--r--src/char/mapif.h48
-rw-r--r--src/char/packets_hc_struct.h45
-rw-r--r--src/char/pincode.c333
-rw-r--r--src/char/pincode.h48
42 files changed, 5717 insertions, 3386 deletions
diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c
index e0f81c61f..f3cf2cff4 100644
--- a/src/char/HPMchar.c
+++ b/src/char/HPMchar.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2014-2015 Hercules Dev Team
+ * Copyright (C) 2014-2018 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
@@ -27,7 +27,9 @@
#include "char/char.h"
#include "char/geoip.h"
#include "char/inter.h"
+#include "char/int_achievement.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"
@@ -36,10 +38,12 @@
#include "char/int_party.h"
#include "char/int_pet.h"
#include "char/int_quest.h"
+#include "char/int_rodex.h"
#include "char/int_storage.h"
#include "char/loginif.h"
#include "char/mapif.h"
#include "char/pincode.h"
+
#include "common/HPMi.h"
#include "common/conf.h"
#include "common/console.h"
@@ -53,6 +57,7 @@
#include "common/mapindex.h"
#include "common/mmo.h"
#include "common/nullpo.h"
+#include "common/packets.h"
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h"
diff --git a/src/char/HPMchar.h b/src/char/HPMchar.h
index 2bf2820f8..0de3b88b8 100644
--- a/src/char/HPMchar.h
+++ b/src/char/HPMchar.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2014-2015 Hercules Dev Team
+ * Copyright (C) 2014-2018 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
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index 7806ce2bb..f159a443f 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -1,7 +1,7 @@
# This file is part of Hercules.
# http://herc.ws - http://github.com/HerculesWS/Hercules
#
-# Copyright (C) 2012-2016 Hercules Dev Team
+# Copyright (C) 2012-2018 Hercules Dev Team
# Copyright (C) Athena Dev Teams
#
# Hercules is free software: you can redistribute it and/or modify
@@ -40,13 +40,13 @@ 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 \
- int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \
- int_quest.c int_storage.c pincode.c
+CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_achievement.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 \
- int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \
- int_quest.h int_storage.h pincode.h
+CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_achievement.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 packets_hc_struct.h
CHAR_PH =
HAVE_MYSQL=@HAVE_MYSQL@
diff --git a/src/char/char.c b/src/char/char.c
index 9314e8c81..330b0639f 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -21,11 +21,12 @@
#define HERCULES_CORE
#include "config/core.h" // CONSOLE_INPUT
-#include "char.h"
+#include "char/char.h"
#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"
@@ -34,10 +35,13 @@
#include "char/int_party.h"
#include "char/int_pet.h"
#include "char/int_quest.h"
+#include "char/int_rodex.h"
#include "char/int_storage.h"
+#include "char/int_achievement.h"
#include "char/inter.h"
#include "char/loginif.h"
#include "char/mapif.h"
+#include "char/packets_hc_struct.h"
#include "char/pincode.h"
#include "common/HPM.h"
@@ -50,6 +54,7 @@
#include "common/mapindex.h"
#include "common/mmo.h"
#include "common/nullpo.h"
+#include "common/packetsstatic_len.h"
#include "common/showmsg.h"
#include "common/socket.h"
#include "common/strlib.h"
@@ -94,50 +99,54 @@ char party_db[256] = "party";
char pet_db[256] = "pet";
char mail_db[256] = "mail"; // MAIL SYSTEM
char auction_db[256] = "auction"; // Auctions System
-char friend_db[256] = "friends";
-char hotkey_db[256] = "hotkey";
+static char friend_db[256] = "friends";
+static char hotkey_db[256] = "hotkey";
char quest_db[256] = "quest";
+char rodex_db[256] = "rodex_mail";
+char rodex_item_db[256] = "rodex_items";
char homunculus_db[256] = "homunculus";
char skill_homunculus_db[256] = "skill_homunculus";
char mercenary_db[256] = "mercenary";
char mercenary_owner_db[256] = "mercenary_owner";
char ragsrvinfo_db[256] = "ragsrvinfo";
char elemental_db[256] = "elemental";
-char account_data_db[256] = "account_data";
+static char account_data_db[256] = "account_data";
char acc_reg_num_db[32] = "acc_reg_num_db";
char acc_reg_str_db[32] = "acc_reg_str_db";
char char_reg_str_db[32] = "char_reg_str_db";
char char_reg_num_db[32] = "char_reg_num_db";
+char char_achievement_db[256] = "char_achievements";
-struct char_interface char_s;
+static struct char_interface char_s;
struct char_interface *chr;
char db_path[1024] = "db";
-char wisp_server_name[NAME_LENGTH] = "Server";
-char login_ip_str[128];
-uint32 login_ip = 0;
-uint16 login_port = 6900;
-char char_ip_str[128];
-char bind_ip_str[128];
-uint32 bind_ip = INADDR_ANY;
-int char_maintenance_min_group_id = 0;
-bool enable_char_creation = true; ///< Whether to allow character creation.
-
-bool name_ignoring_case = false; // Allow or not identical name for characters but with a different case by [Yor]
+static char wisp_server_name[NAME_LENGTH] = "Server";
+static char login_ip_str[128];
+static uint32 login_ip = 0;
+static uint16 login_port = 6900;
+static char char_ip_str[128];
+static char bind_ip_str[128];
+static uint32 bind_ip = INADDR_ANY;
+static int char_maintenance_min_group_id = 0;
+static bool enable_char_creation = true; ///< Whether to allow character creation.
+
+static bool name_ignoring_case = false; // Allow or not identical name for characters but with a different case by [Yor]
int char_name_option = 0; // Option to know which letters/symbols are authorized in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor]
-char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the requested name cannot be determined
+static char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the requested name cannot be determined
#define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex]
char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) in a character name. by [Yor]
-int char_del_level = 0; ///< From which level you can delete character [Lupus]
-int char_del_delay = 86400;
-bool char_aegis_delete = false; ///< Verify if char is in guild/party or char and reacts as Aegis does (disallow deletion), @see chr->delete2_req.
+static int char_del_level = 0; ///< From which level you can delete character [Lupus]
+static int char_del_delay = 86400;
+static bool char_aegis_delete = false; ///< Verify if char is in guild/party or char and reacts as Aegis does (disallow deletion), @see chr->delete2_req.
+static bool char_aegis_rename = false; // whether or not the player can be renamed while in party/guild
-int max_connect_user = -1;
-int gm_allow_group = -1;
+static int max_connect_user = -1;
+static int gm_allow_group = -1;
int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
-int start_zeny = 0;
+static int start_zeny = 0;
/// Start items for new characters
struct start_item_s {
@@ -146,28 +155,28 @@ struct start_item_s {
int loc;
bool stackable;
};
-VECTOR_DECL(struct start_item_s) start_items;
+static VECTOR_DECL(struct start_item_s) start_items;
int guild_exp_rate = 100;
//Custom limits for the fame lists. [Skotlex]
-int fame_list_size_chemist = MAX_FAME_LIST;
-int fame_list_size_smith = MAX_FAME_LIST;
-int fame_list_size_taekwon = MAX_FAME_LIST;
+static int fame_list_size_chemist = MAX_FAME_LIST;
+static int fame_list_size_smith = MAX_FAME_LIST;
+static int fame_list_size_taekwon = MAX_FAME_LIST;
// Char-server-side stored fame lists [DracoRPG]
-struct fame_list smith_fame_list[MAX_FAME_LIST];
-struct fame_list chemist_fame_list[MAX_FAME_LIST];
-struct fame_list taekwon_fame_list[MAX_FAME_LIST];
+static struct fame_list smith_fame_list[MAX_FAME_LIST];
+static struct fame_list chemist_fame_list[MAX_FAME_LIST];
+static struct fame_list taekwon_fame_list[MAX_FAME_LIST];
// Initial position (it's possible to set it in conf file)
#ifdef RENEWAL
- struct point start_point = { 0, 97, 90 };
+static struct point start_point = { 0, 97, 90 };
#else
- struct point start_point = { 0, 53, 111 };
+static struct point start_point = { 0, 53, 111 };
#endif
-unsigned short skillid2idx[MAX_SKILL_ID];
+static unsigned short skillid2idx[MAX_SKILL_ID];
//-----------------------------------------------------
// Auth database
@@ -196,7 +205,7 @@ static struct DBData char_create_online_char_data(union DBKey key, va_list args)
return DB->ptr2data(character);
}
-void char_set_account_online(int account_id)
+static void char_set_account_online(int account_id)
{
WFIFOHEAD(chr->login_fd,6);
WFIFOW(chr->login_fd,0) = 0x272b;
@@ -204,7 +213,7 @@ void char_set_account_online(int account_id)
WFIFOSET(chr->login_fd,6);
}
-void char_set_account_offline(int account_id)
+static void char_set_account_offline(int account_id)
{
WFIFOHEAD(chr->login_fd,6);
WFIFOW(chr->login_fd,0) = 0x272c;
@@ -212,7 +221,7 @@ void char_set_account_offline(int account_id)
WFIFOSET(chr->login_fd,6);
}
-void char_set_char_charselect(int account_id)
+static void char_set_char_charselect(int account_id)
{
struct online_char_data* character;
@@ -236,7 +245,7 @@ void char_set_char_charselect(int account_id)
chr->set_account_online(account_id);
}
-void char_set_char_online(int map_id, int char_id, int account_id)
+static void char_set_char_online(int map_id, int char_id, int account_id)
{
struct online_char_data* character;
struct mmo_charstatus *cp;
@@ -276,7 +285,7 @@ void char_set_char_online(int map_id, int char_id, int account_id)
chr->set_account_online(account_id);
}
-void char_set_char_offline(int char_id, int account_id)
+static void char_set_char_offline(int char_id, int account_id)
{
struct online_char_data* character;
@@ -287,10 +296,18 @@ void char_set_char_offline(int char_id, int account_id)
}
else
{
- struct mmo_charstatus* cp = (struct mmo_charstatus*)idb_get(chr->char_db_,char_id);
+ struct mmo_charstatus *cp = (struct mmo_charstatus*) idb_get(chr->char_db_, char_id);
+ /* Character Achievements */
+ struct char_achievements *c_ach = (struct char_achievements *) idb_get(inter_achievement->char_achievements, char_id);
+
inter_guild->CharOffline(char_id, cp?cp->guild_id:-1);
- if (cp)
+
+ if (cp != NULL)
idb_remove(chr->char_db_,char_id);
+ if (c_ach != NULL) {
+ VECTOR_CLEAR(*c_ach);
+ idb_remove(inter_achievement->char_achievements, char_id);
+ }
if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) )
Sql_ShowDebug(inter->sql_handle);
@@ -365,7 +382,7 @@ static int char_db_kickoffline(union DBKey key, struct DBData *data, va_list ap)
return 1;
}
-void char_set_login_all_offline(void)
+static void char_set_login_all_offline(void)
{
//Tell login-server to also mark all our characters as offline.
WFIFOHEAD(chr->login_fd,2);
@@ -373,7 +390,7 @@ void char_set_login_all_offline(void)
WFIFOSET(chr->login_fd,2);
}
-void char_set_all_offline(int id)
+static void char_set_all_offline(int id)
{
if (id < 0)
ShowNotice("Sending all users offline.\n");
@@ -386,7 +403,7 @@ void char_set_all_offline(int id)
chr->set_login_all_offline();
}
-void char_set_all_offline_sql(void)
+static void char_set_all_offline_sql(void)
{
//Set all players to 'OFFLINE'
if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `online` = '0'", char_db) )
@@ -408,7 +425,7 @@ static struct DBData char_create_charstatus(union DBKey key, va_list args)
return DB->ptr2data(cp);
}
-int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
+static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
{
int i = 0;
int count = 0;
@@ -428,7 +445,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
//map inventory data
if( memcmp(p->inventory, cp->inventory, sizeof(p->inventory)) ) {
- if (!chr->memitemdata_to_sql(p->inventory, MAX_INVENTORY, p->char_id, TABLE_INVENTORY))
+ if (!chr->memitemdata_to_sql(p->inventory, p->char_id, TABLE_INVENTORY))
strcat(save_status, " inventory");
else
errors++;
@@ -436,20 +453,12 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
//map cart data
if( memcmp(p->cart, cp->cart, sizeof(p->cart)) ) {
- if (!chr->memitemdata_to_sql(p->cart, MAX_CART, p->char_id, TABLE_CART))
+ if (!chr->memitemdata_to_sql(p->cart, p->char_id, TABLE_CART))
strcat(save_status, " cart");
else
errors++;
}
- //map storage data
- if( memcmp(p->storage.items, cp->storage.items, sizeof(p->storage.items)) ) {
- if (!chr->memitemdata_to_sql(p->storage.items, MAX_STORAGE, p->account_id, TABLE_STORAGE))
- strcat(save_status, " storage");
- else
- errors++;
- }
-
if (
(p->base_exp != cp->base_exp) || (p->base_level != cp->base_level) ||
(p->job_level != cp->job_level) || (p->job_exp != cp->job_exp) ||
@@ -463,42 +472,53 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->int_ != cp->int_) || (p->dex != cp->dex) || (p->luk != cp->luk) ||
(p->option != cp->option) ||
(p->party_id != cp->party_id) || (p->guild_id != cp->guild_id) ||
- (p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) ||
- (p->ele_id != cp->ele_id) || (p->shield != cp->shield) || (p->head_top != cp->head_top) ||
- (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
- (p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->robe != cp->robe) ||
+ (p->pet_id != cp->pet_id) || (p->look.weapon != cp->look.weapon) || (p->hom_id != cp->hom_id) ||
+ (p->ele_id != cp->ele_id) || (p->look.shield != cp->look.shield) || (p->look.head_top != cp->look.head_top) ||
+ (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) || (p->attendance_count != cp->attendance_count) ||
+ (p->attendance_timer != cp->attendance_timer) || (p->title_id != cp->title_id) || (p->inventorySize != cp->inventorySize)
) {
//Save status
unsigned int opt = 0;
+ if (p->inventorySize <= 0 || p->inventorySize > MAX_INVENTORY) {
+ ShowError("Wrong inventorySize field: %d. Must be in range 1 to %d. Character %s (CID: %d, AID: %d)\n",
+ p->inventorySize, MAX_INVENTORY, p->name, p->char_id, p->account_id);
+ Assert_report(0);
+ p->inventorySize = FIXED_INVENTORY_SIZE;
+ }
+
if( p->allow_party )
opt |= OPT_ALLOW_PARTY;
if( p->show_equip )
opt |= OPT_SHOW_EQUIP;
if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
- "`base_exp`='%u', `job_exp`='%u', `zeny`='%d',"
+ "`base_exp`='%"PRIu64"', `job_exp`='%"PRIu64"', `zeny`='%d',"
"`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d',"
"`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d',"
"`option`='%u',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d',"
"`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"',`attendance_count`='%d',`attendance_timer`='%"PRId64"',"
+ "`title_id`='%d', `inventory_size`='%d'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point,
p->str, p->agi, p->vit, p->int_, p->dex, p->luk,
p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, p->ele_id,
- p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
+ p->look.weapon, p->look.shield, p->look.head_top, p->look.head_mid, p->look.head_bottom,
mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y,
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->robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
- p->hotkey_rowshift,
+ p->look.robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
+ p->hotkey_rowshift,p->clan_id,p->last_login, p->attendance_count, p->attendance_timer,
+ p->title_id, p->inventorySize,
p->account_id, p->char_id) )
{
Sql_ShowDebug(inter->sql_handle);
@@ -603,7 +623,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", skill_db);
//insert here.
- for( i = 0, count = 0; i < MAX_SKILL; ++i ) {
+ for (i = 0, count = 0; i < MAX_SKILL_DB; ++i) {
if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) {
if( p->skill[i].lv == 0 && ( p->skill[i].flag == SKILL_FLAG_PERM_GRANTED || p->skill[i].flag == SKILL_FLAG_PERMANENT ) )
continue;
@@ -702,176 +722,290 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
}
/**
- * Saves an array of 'item' entries into the specified table.
- *
- * @param items The items array.
- * @param max The array size.
- * @param id The character/account/guild ID (depending on tableswitch).
- * @param tableswitch The type of table (@see enum inventory_table_type).
- * @return Error code.
- * @retval 0 in case of success.
+ * Gets a player object's item data from an sql table. [Smokexyz/Hercules]
+ * @param[in|out] items reference to the item list of a character/account/guild.
+ * @param[in] max Max amount of items to be pulled into the list.
+ * @param[in] guid Unique ID of the player object (account_id, char_id, guild_id).
+ * @param[in] table Table to be used for the transaction.
+ * @return -1 on failure or number of items added to the list if successful.
*/
-int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch)
+static int char_getitemdata_from_sql(struct item *items, int max, int guid, enum inventory_table_type table)
{
- StringBuf buf;
+ int i = 0;
struct SqlStmt *stmt = NULL;
- int i, j;
const char *tablename = NULL;
const char *selectoption = NULL;
bool has_favorite = false;
+ StringBuf buf;
struct item item = { 0 }; // temp storage variable
- bool *flag = NULL; // bit array for inventory matching
- bool found;
- int errors = 0;
- nullpo_ret(items);
-
- switch (tableswitch) {
- case TABLE_INVENTORY: tablename = inventory_db; selectoption = "char_id"; has_favorite = true; break;
- case TABLE_CART: tablename = cart_db; selectoption = "char_id"; break;
- case TABLE_STORAGE: tablename = storage_db; selectoption = "account_id"; break;
- case TABLE_GUILD_STORAGE: tablename = guild_storage_db; selectoption = "guild_id"; break;
+ nullpo_retr(-1, items);
+ Assert_retr(-1, guid > 0);
+ Assert_retr(-1, max > 0);
+
+ // Initialize the array.
+ memset(items, 0x0, sizeof(struct item) * max);
+
+ switch (table) {
+ case TABLE_INVENTORY:
+ tablename = inventory_db;
+ selectoption = "char_id";
+ has_favorite = true;
+ break;
+ case TABLE_CART:
+ tablename = cart_db;
+ selectoption = "char_id";
+ break;
+ case TABLE_GUILD_STORAGE:
+ tablename = guild_storage_db;
+ selectoption = "guild_id";
+ break;
default:
- ShowError("Invalid table name!\n");
- Assert_retr(1, tableswitch);
+ ShowError("char_getitemdata_from_sql: Invalid table type %d!\n", (int) table);
+ Assert_retr(-1, table);
+ return -1;
}
- // The following code compares inventory with current database values
- // and performs modification/deletion/insertion only on relevant rows.
- // This approach is more complicated than a trivial delete&insert, but
- // it significantly reduces cpu load on the database server.
-
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
- for (j = 0; j < MAX_SLOTS; ++j)
- StrBuf->Printf(&buf, ", `card%d`", j);
+ for(i = 0; i < MAX_SLOTS; i++)
+ StrBuf->Printf(&buf, ", `card%d`", i);
+ for(i = 0; i < MAX_ITEM_OPTIONS; i++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
if (has_favorite)
StrBuf->AppendStr(&buf, ", `favorite`");
- StrBuf->Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id);
+ StrBuf->Printf(&buf, " FROM `%s` WHERE `%s`=?", tablename, selectoption);
stmt = SQL->StmtMalloc(inter->sql_handle);
if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
- || SQL_ERROR == SQL->StmtExecute(stmt)) {
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &guid, sizeof guid)
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
- return 1;
+ return -1;
}
- SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &item.equip, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &item.bound, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, 0, NULL, NULL);
- for (j = 0; j < MAX_SLOTS; ++j)
- SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
- if (has_favorite)
- SQL->StmtBindColumn(stmt, 10+MAX_SLOTS, SQLDT_UCHAR, &item.favorite, 0, NULL, NULL);
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, sizeof item.id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &item.nameid, sizeof item.nameid, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, sizeof item.amount, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &item.equip, sizeof item.equip, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &item.identify, sizeof item.identify, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &item.refine, sizeof item.refine, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, sizeof item.attribute, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, sizeof item.expire_time, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &item.bound, sizeof item.bound, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, sizeof item.unique_id, NULL, NULL)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ }
- // bit array indicating which inventory items have already been matched
- flag = aCalloc(max, sizeof(bool));
+ for (i = 0; i < MAX_SLOTS; i++) {
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt, 10 + i, SQLDT_INT, &item.card[i], sizeof item.card[i], NULL, NULL))
+ SqlStmt_ShowDebug(stmt);
+ }
- while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
- found = false;
- // search for the presence of the item in the char's inventory
- for (i = 0; i < max; ++i) {
- // skip empty and already matched entries
- if (items[i].nameid == 0 || flag[i])
- continue;
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt, 10 + MAX_SLOTS + i * 2, SQLDT_INT16, &item.option[i].index, sizeof item.option[i].index, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 11 + MAX_SLOTS + i * 2, SQLDT_INT16, &item.option[i].value, sizeof item.option[i].index, NULL, NULL))
+ SqlStmt_ShowDebug(stmt);
+ }
- if (items[i].nameid == item.nameid
- && items[i].unique_id == item.unique_id
- && items[i].card[0] == item.card[0]
- && items[i].card[2] == item.card[2]
- && items[i].card[3] == item.card[3]
- ) {
- // They are the same item.
- ARR_FIND(0, MAX_SLOTS, j, items[i].card[j] != item.card[j]);
- if (j == MAX_SLOTS
- && items[i].amount == item.amount
- && items[i].equip == item.equip
- && items[i].identify == item.identify
- && items[i].refine == item.refine
- && items[i].attribute == item.attribute
- && items[i].expire_time == item.expire_time
- && items[i].bound == item.bound
- && (!has_favorite || items[i].favorite == item.favorite)
- ) {
- ; //Do nothing.
- } else {
- // update all fields.
- StrBuf->Clear(&buf);
- StrBuf->Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%u', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `bound`='%d'",
- tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].bound);
- for (j = 0; j < MAX_SLOTS; ++j)
- StrBuf->Printf(&buf, ", `card%d`='%d'", j, items[i].card[j]);
- if (has_favorite)
- StrBuf->Printf(&buf, ", `favorite`='%d'", items[i].favorite);
- StrBuf->Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
+ if (has_favorite) {
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt, 10 + MAX_SLOTS + MAX_ITEM_OPTIONS * 2, SQLDT_CHAR, &item.favorite, sizeof item.favorite, NULL, NULL))
+ SqlStmt_ShowDebug(stmt);
+ }
+
+ if (SQL->StmtNumRows(stmt) > 0 ) {
+ i = 0;
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt) && i < max) {
+ items[i++] = item;
+ }
+ }
+
+ SQL->StmtFree(stmt);
+ StrBuf->Destroy(&buf);
+
+ return i;
+}
+
+/**
+ * Saves an array of 'item' entries into the specified table. [Smokexyz/Hercules]
+ * @param[in] items The items array.
+ * @param[in] guid The character/account/guild ID (depending on table).
+ * @param[in] tableswitch The type of table (@see enum inventory_table_type).
+ * @retval -1 in case of failure, or number of changes made within the table.
+ */
+static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum inventory_table_type table)
+{
+ StringBuf buf;
+ int i = 0, j = 0;
+ const char *tablename = NULL;
+ const char *selectoption = NULL;
+ bool has_favorite = false;
+ struct item *cp_items = NULL; // temp item storage variable
+ bool *matched_p = NULL;
+ int total_updates = 0, total_deletes = 0, total_inserts = 0, total_changes = 0;
+ int item_count = 0, db_max = 0;
+
+ nullpo_ret(p_items);
+
+ switch (table) {
+ case TABLE_INVENTORY:
+ tablename = inventory_db;
+ selectoption = "char_id";
+ has_favorite = true;
+ item_count = MAX_INVENTORY;
+ break;
+ case TABLE_CART:
+ tablename = cart_db;
+ selectoption = "char_id";
+ item_count = MAX_CART;
+ break;
+ case TABLE_GUILD_STORAGE:
+ tablename = guild_storage_db;
+ selectoption = "guild_id";
+ item_count = MAX_GUILD_STORAGE;
+ break;
+ default:
+ ShowError("Invalid table type %d!\n", (int) table);
+ Assert_retr(-1, table);
+ return -1;
+ }
+
+ cp_items = aCalloc(item_count, sizeof(struct item));
+ matched_p = aCalloc(item_count, sizeof(bool));
+
+ StrBuf->Init(&buf);
+
+ /**
+ * If the storage table is not empty, check for items and replace or delete where needed.
+ */
+ if ((db_max = chr->getitemdata_from_sql(cp_items, item_count, guid, table)) > 0) {
+ int *deletes = aCalloc(db_max, sizeof(struct item));
+
+ for (i = 0; i < db_max; i++) {
+ struct item *cp_it = &cp_items[i];
+
+ ARR_FIND(0, item_count, j,
+ matched_p[j] != true
+ && p_items[j].nameid != 0
+ && cp_it->nameid == p_items[j].nameid
+ && cp_it->unique_id == p_items[j].unique_id
+ && memcmp(p_items[j].card, cp_it->card, sizeof(int) * MAX_SLOTS) == 0
+ && memcmp(p_items[j].option, cp_it->option, 5 * MAX_ITEM_OPTIONS) == 0);
+
+ if (j < item_count) { // Item found.
+ matched_p[j] = true; // Mark the item as matched.
+
+ // If the amount has changed, set for replacement with current item properties.
+ if (memcmp(cp_it, &p_items[j], sizeof(struct item)) != 0) {
+ int k = 0;
+
+ if (total_updates == 0) {
+ StrBuf->Clear(&buf);
+ StrBuf->Printf(&buf, "REPLACE INTO `%s` (`id`, `%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", tablename, selectoption);
+ for (k = 0; k < MAX_SLOTS; k++)
+ StrBuf->Printf(&buf, ", `card%d`", k);
+ for (k = 0; k < MAX_ITEM_OPTIONS; k++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", k, k);
+ StrBuf->AppendStr(&buf, ", `expire_time`, `bound`, `unique_id`");
+ if (has_favorite)
+ StrBuf->AppendStr(&buf, ", `favorite`");
+
+ StrBuf->AppendStr(&buf, ") VALUES ");
- if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
- Sql_ShowDebug(inter->sql_handle);
- errors++;
}
- }
- found = flag[i] = true; //Item dealt with,
- break; //skip to next item in the db.
+ StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%d', '%u', '%d', '%d', '%d'",
+ total_updates > 0 ? ", " : "", cp_it->id, guid, p_items[j].nameid, p_items[j].amount, p_items[j].equip, p_items[j].identify, p_items[j].refine, p_items[j].attribute);
+ for (k = 0; k < MAX_SLOTS; k++)
+ StrBuf->Printf(&buf, ", '%d'", p_items[j].card[k]);
+ for (k = 0; k < MAX_ITEM_OPTIONS; ++k)
+ StrBuf->Printf(&buf, ", '%d', '%d'", p_items[j].option[k].index, p_items[j].option[k].value);
+ StrBuf->Printf(&buf, ", '%u', '%d', '%"PRIu64"'", p_items[j].expire_time, p_items[j].bound, p_items[j].unique_id);
+ if (has_favorite)
+ StrBuf->Printf(&buf, ", %d", p_items[j].favorite);
+
+ StrBuf->AppendStr(&buf, ")");
+
+ total_updates++;
+ }
+ } else { // Doesn't exist in the table, set for deletion.
+ deletes[total_deletes++] = cp_it->id;
}
}
- if (!found) {
- // Item not present in inventory, remove it.
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", tablename, item.id)) {
+
+ if (total_updates > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
+ Sql_ShowDebug(inter->sql_handle);
+
+ /**
+ * Handle deletions, if any.
+ */
+ if (total_deletes > 0) {
+ StrBuf->Clear(&buf);
+ StrBuf->Printf(&buf, "DELETE FROM `%s` WHERE `id` IN (", tablename);
+ for (i = 0; i < total_deletes; i++)
+ StrBuf->Printf(&buf, "%s'%d'", i == 0 ? "" : ", ", deletes[i]);
+
+ StrBuf->AppendStr(&buf, ");");
+
+ if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
Sql_ShowDebug(inter->sql_handle);
- errors++;
- }
}
+
+ aFree(deletes);
}
- SQL->StmtFree(stmt);
- StrBuf->Clear(&buf);
- StrBuf->Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", tablename, selectoption);
- for (j = 0; j < MAX_SLOTS; ++j)
- StrBuf->Printf(&buf, ", `card%d`", j);
- if (has_favorite)
- StrBuf->AppendStr(&buf, ", `favorite`");
- StrBuf->AppendStr(&buf, ") VALUES ");
+ /**
+ * Check for new items and add if required.
+ */
+ for (i = 0; i < item_count; i++) {
+ const struct item *p_it = &p_items[i];
- found = false;
- // insert non-matched items into the db as new items
- for (i = 0; i < max; ++i) {
- // skip empty and already matched entries
- if (items[i].nameid == 0 || flag[i])
+ if (matched_p[i] || p_it->nameid == 0)
continue;
- if (found)
- StrBuf->AppendStr(&buf, ",");
- else
- found = true;
+ if (total_inserts == 0) {
+ StrBuf->Clear(&buf);
+ StrBuf->Printf(&buf, "INSERT INTO `%s` (`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", tablename, selectoption);
+ for (j = 0; j < MAX_SLOTS; ++j)
+ StrBuf->Printf(&buf, ", `card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j);
+ if (has_favorite)
+ StrBuf->AppendStr(&buf, ", `favorite`");
+ StrBuf->AppendStr(&buf, ") VALUES ");
+ }
+
+ StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'",
+ total_inserts > 0 ? ", " : "", guid, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine,
+ p_it->attribute, p_it->expire_time, p_it->bound, p_it->unique_id);
- StrBuf->Printf(&buf, "('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'",
- id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].bound, items[i].unique_id);
for (j = 0; j < MAX_SLOTS; ++j)
- StrBuf->Printf(&buf, ", '%d'", items[i].card[j]);
+ StrBuf->Printf(&buf, ", '%d'", p_it->card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", '%d', '%d'", p_it->option[j].index, p_it->option[j].value);
+
if (has_favorite)
- StrBuf->Printf(&buf, ", '%d'", items[i].favorite);
+ StrBuf->Printf(&buf, ", '%d'", p_it->favorite);
+
StrBuf->AppendStr(&buf, ")");
+
+ total_inserts++;
}
- if (found && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
+ if (total_inserts > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
Sql_ShowDebug(inter->sql_handle);
- errors++;
- }
StrBuf->Destroy(&buf);
- aFree(flag);
- return errors;
+ aFree(cp_items);
+ aFree(matched_p);
+
+ ShowInfo("%s save complete - guid: %d (replace: %d, insert: %d, delete: %d)\n", tablename, guid, total_updates, total_inserts, total_deletes);
+
+ return total_changes;
}
/**
@@ -887,7 +1021,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
* @retval SEX_FEMALE if the per-character sex is female
* @retval 99 if the per-character sex is not defined or the current PACKETVER doesn't support it.
*/
-int char_mmo_gender(const struct char_session_data *sd, const struct mmo_charstatus *p, char sex)
+static int char_mmo_gender(const struct char_session_data *sd, const struct mmo_charstatus *p, char sex)
{
#if PACKETVER >= 20141016
(void)sd; (void)p; // Unused
@@ -925,7 +1059,7 @@ int char_mmo_gender(const struct char_session_data *sd, const struct mmo_charsta
//=====================================================================================================
// Loads the basic character rooster for the given account. Returns total buffer used.
-int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
+static int char_mmo_chars_fromsql(struct char_session_data *sd, uint8 *buf, int *count)
{
struct SqlStmt *stmt;
struct mmo_charstatus p;
@@ -934,6 +1068,9 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
time_t unban_time = 0;
char sex[2];
+ if (count)
+ *count = 0;
+
nullpo_ret(sd);
nullpo_ret(buf);
@@ -955,84 +1092,94 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
"`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
"`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
- "`robe`,`slotchange`,`unban_time`,`sex`"
+ "`robe`,`slotchange`,`unban_time`,`sex`,`title_id`,`inventory_size`"
" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UCHAR, &p.slot, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &p.name, sizeof(p.name), NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_SHORT, &p.class, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT, &p.base_level, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &p.job_level, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_UINT, &p.base_exp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &p.job_exp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT, &p.zeny, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_SHORT, &p.str, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_SHORT, &p.agi, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_SHORT, &p.vit, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_SHORT, &p.int_, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_SHORT, &p.dex, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_SHORT, &p.luk, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 15, SQLDT_INT, &p.max_hp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 16, SQLDT_INT, &p.hp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 17, SQLDT_INT, &p.max_sp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 18, SQLDT_INT, &p.sp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 19, SQLDT_INT, &p.status_point, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 20, SQLDT_INT, &p.skill_point, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 21, SQLDT_UINT, &p.option, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 22, SQLDT_UCHAR, &p.karma, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 23, SQLDT_SHORT, &p.manner, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 24, SQLDT_SHORT, &p.hair, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 25, SQLDT_SHORT, &p.hair_color, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 26, SQLDT_SHORT, &p.clothes_color, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_SHORT, &p.body, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_SHORT, &p.weapon, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_SHORT, &p.shield, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_SHORT, &p.head_top, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_USHORT, &p.rename, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_SHORT, &p.robe, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_USHORT, &p.slotchange, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_LONG, &unban_time, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p.char_id, sizeof p.char_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UCHAR, &p.slot, sizeof p.slot, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &p.name, sizeof p.name, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_INT16, &p.class, sizeof p.class, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT, &p.base_level, sizeof p.base_level, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &p.job_level, sizeof p.job_level, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_UINT64, &p.base_exp, sizeof p.base_exp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT64, &p.job_exp, sizeof p.job_exp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT, &p.zeny, sizeof p.zeny, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_SHORT, &p.str, sizeof p.str, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_SHORT, &p.agi, sizeof p.agi, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_SHORT, &p.vit, sizeof p.vit, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_SHORT, &p.int_, sizeof p.int_, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_SHORT, &p.dex, sizeof p.dex, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_SHORT, &p.luk, sizeof p.luk, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 15, SQLDT_INT, &p.max_hp, sizeof p.max_hp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 16, SQLDT_INT, &p.hp, sizeof p.hp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 17, SQLDT_INT, &p.max_sp, sizeof p.max_sp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 18, SQLDT_INT, &p.sp, sizeof p.sp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 19, SQLDT_INT, &p.status_point, sizeof p.status_point, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 20, SQLDT_INT, &p.skill_point, sizeof p.skill_point, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 21, SQLDT_UINT, &p.option, sizeof p.option, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 22, SQLDT_UCHAR, &p.karma, sizeof p.karma, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 23, SQLDT_SHORT, &p.manner, sizeof p.manner, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 24, SQLDT_SHORT, &p.hair, sizeof p.hair, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 25, SQLDT_SHORT, &p.hair_color, sizeof p.hair_color, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 26, SQLDT_SHORT, &p.clothes_color, sizeof p.clothes_color, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_INT, &p.body, sizeof p.body, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_INT, &p.look.weapon, sizeof p.look.weapon, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_INT, &p.look.shield, sizeof p.look.shield, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_INT, &p.look.head_top, sizeof p.look.head_top, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_INT, &p.look.head_mid, sizeof p.look.head_mid, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_INT, &p.look.head_bottom, sizeof p.look.head_bottom, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_STRING, &last_map, sizeof last_map, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_USHORT, &p.rename, sizeof p.rename, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_TIME, &p.delete_date, sizeof p.delete_date, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_INT, &p.look.robe, sizeof p.look.robe, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_USHORT, &p.slotchange, sizeof p.slotchange, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_TIME, &unban_time, sizeof unban_time, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_ENUM, &sex, sizeof sex, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_INT, &p.title_id, sizeof p.title_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_INT, &p.inventorySize, sizeof p.inventorySize, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
return 0;
}
- for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->StmtNextRow(stmt); i++ ) {
+ int tmpCount = 0;
+ for (i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->StmtNextRow(stmt); i++) {
if (p.slot >= MAX_CHARS)
continue;
+ if (p.inventorySize <= 0 || p.inventorySize > MAX_INVENTORY) {
+ ShowError("Wrong inventorySize field: %d. Must be in range 1 to %d. Character %s (CID: %d, AID: %d)\n",
+ p.inventorySize, MAX_INVENTORY, p.name, p.char_id, p.account_id);
+ Assert_report(0);
+ p.inventorySize = FIXED_INVENTORY_SIZE;
+ }
p.last_point.map = mapindex->name2id(last_map);
sd->found_char[p.slot] = p.char_id;
sd->unban_time[p.slot] = unban_time;
p.sex = chr->mmo_gender(sd, &p, sex[0]);
j += chr->mmo_char_tobuf(WBUFP(buf, j), &p);
+ tmpCount ++;
}
- memset(sd->new_name,0,sizeof(sd->new_name));
+ memset(sd->new_name, 0, sizeof(sd->new_name));
SQL->StmtFree(stmt);
+ if (count)
+ *count = tmpCount;
return j;
}
//=====================================================================================================
-int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything)
+static int char_mmo_char_fromsql(int char_id, struct mmo_charstatus *p, bool load_everything)
{
- int i,j;
+ int i = 0;
char t_msg[128] = "";
struct mmo_charstatus* cp;
- StringBuf buf;
struct SqlStmt *stmt;
char last_map[MAP_NAME_LENGTH_EXT];
char save_map[MAP_NAME_LENGTH_EXT];
char point_map[MAP_NAME_LENGTH_EXT];
struct point tmp_point;
- struct item tmp_item;
struct s_skill tmp_skill;
struct s_friend tmp_friend;
#ifdef HOTKEY_SAVING
@@ -1046,6 +1193,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
nullpo_ret(p);
memset(p, 0, sizeof(struct mmo_charstatus));
+ p->inventorySize = FIXED_INVENTORY_SIZE;
if (chr->show_save_log)
ShowInfo("Char load request (%d)\n", char_id);
@@ -1064,69 +1212,76 @@ 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`, `attendance_count`, `attendance_timer`,"
+ "`title_id`, `inventory_size`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p->char_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &p->account_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UCHAR, &p->slot, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_STRING, &p->name, sizeof(p->name), NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_SHORT, &p->class, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &p->base_level, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_INT, &p->job_level, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &p->base_exp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_UINT, &p->job_exp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_INT, &p->zeny, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_SHORT, &p->str, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_SHORT, &p->agi, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_SHORT, &p->vit, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_SHORT, &p->int_, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_SHORT, &p->dex, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 15, SQLDT_SHORT, &p->luk, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 16, SQLDT_INT, &p->max_hp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 17, SQLDT_INT, &p->hp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 18, SQLDT_INT, &p->max_sp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 19, SQLDT_INT, &p->sp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 20, SQLDT_INT, &p->status_point, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 21, SQLDT_INT, &p->skill_point, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 22, SQLDT_UINT, &p->option, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 23, SQLDT_UCHAR, &p->karma, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 24, SQLDT_SHORT, &p->manner, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 25, SQLDT_INT, &p->party_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 26, SQLDT_INT, &p->guild_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_INT, &p->pet_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_INT, &p->hom_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_INT, &p->ele_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_SHORT, &p->hair, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_SHORT, &p->body, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_SHORT, &p->weapon, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_SHORT, &p->shield, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_SHORT, &p->head_top, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_SHORT, &p->head_mid, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_SHORT, &p->head_bottom, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_SHORT, &p->last_point.x, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_SHORT, &p->last_point.y, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 42, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 43, SQLDT_SHORT, &p->save_point.x, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 44, SQLDT_SHORT, &p->save_point.y, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 45, SQLDT_INT, &p->partner_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 46, SQLDT_INT, &p->father, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 47, SQLDT_INT, &p->mother, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 48, SQLDT_INT, &p->child, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 49, SQLDT_INT, &p->fame, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 50, SQLDT_USHORT, &p->rename, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 51, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 52, SQLDT_SHORT, &p->robe, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_USHORT, &p->slotchange, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UINT, &opt, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UCHAR, &p->font, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_UINT, &p->uniqueitem_counter, 0, 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, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p->char_id, sizeof p->char_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &p->account_id, sizeof p->account_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UCHAR, &p->slot, sizeof p->slot, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_STRING, &p->name, sizeof p->name, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT16, &p->class, sizeof p->class, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &p->base_level, sizeof p->base_level, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_INT, &p->job_level, sizeof p->job_level, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT64, &p->base_exp, sizeof p->base_exp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_UINT64, &p->job_exp, sizeof p->job_exp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_INT, &p->zeny, sizeof p->zeny, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_SHORT, &p->str, sizeof p->str, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_SHORT, &p->agi, sizeof p->agi, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_SHORT, &p->vit, sizeof p->vit, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_SHORT, &p->int_, sizeof p->int_, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_SHORT, &p->dex, sizeof p->dex, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 15, SQLDT_SHORT, &p->luk, sizeof p->luk, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 16, SQLDT_INT, &p->max_hp, sizeof p->max_hp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 17, SQLDT_INT, &p->hp, sizeof p->hp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 18, SQLDT_INT, &p->max_sp, sizeof p->max_sp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 19, SQLDT_INT, &p->sp, sizeof p->sp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 20, SQLDT_INT, &p->status_point, sizeof p->status_point, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 21, SQLDT_INT, &p->skill_point, sizeof p->skill_point, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 22, SQLDT_UINT, &p->option, sizeof p->option, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 23, SQLDT_UCHAR, &p->karma, sizeof p->karma, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 24, SQLDT_SHORT, &p->manner, sizeof p->manner, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 25, SQLDT_INT, &p->party_id, sizeof p->party_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 26, SQLDT_INT, &p->guild_id, sizeof p->guild_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_INT, &p->pet_id, sizeof p->pet_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_INT, &p->hom_id, sizeof p->hom_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_INT, &p->ele_id, sizeof p->ele_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_SHORT, &p->hair, sizeof p->hair, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, sizeof p->hair_color, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, sizeof p->clothes_color, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_INT, &p->body, sizeof p->body, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_INT, &p->look.weapon, sizeof p->look.weapon, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_INT, &p->look.shield, sizeof p->look.shield, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_INT, &p->look.head_top, sizeof p->look.head_top, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_INT, &p->look.head_mid, sizeof p->look.head_mid, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_INT, &p->look.head_bottom, sizeof p->look.head_bottom, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_STRING, &last_map, sizeof last_map, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_INT16, &p->last_point.x, sizeof p->last_point.x, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_INT16, &p->last_point.y, sizeof p->last_point.y, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 42, SQLDT_STRING, &save_map, sizeof save_map, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 43, SQLDT_INT16, &p->save_point.x, sizeof p->save_point.x, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 44, SQLDT_INT16, &p->save_point.y, sizeof p->save_point.y, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 45, SQLDT_INT, &p->partner_id, sizeof p->partner_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 46, SQLDT_INT, &p->father, sizeof p->father, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 47, SQLDT_INT, &p->mother, sizeof p->mother, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 48, SQLDT_INT, &p->child, sizeof p->child, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 49, SQLDT_INT, &p->fame, sizeof p->fame, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 50, SQLDT_USHORT, &p->rename, sizeof p->rename, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 51, SQLDT_TIME, &p->delete_date, sizeof p->delete_date, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 52, SQLDT_INT, &p->look.robe, sizeof p->look.robe, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_USHORT, &p->slotchange, sizeof p->slotchange, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UINT, &opt, sizeof opt, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UCHAR, &p->font, sizeof p->font, NULL, NULL)
+ || 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)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 61, SQLDT_SHORT, &p->attendance_count, sizeof p->attendance_count, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 62, SQLDT_INT64, &p->attendance_timer, sizeof p->attendance_timer, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 63, SQLDT_INT, &p->title_id, sizeof p->title_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 64, SQLDT_INT, &p->inventorySize, sizeof p->inventorySize, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
@@ -1158,6 +1313,13 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
p->save_point.y = mapindex->default_y;
}
+ if (p->inventorySize <= 0 || p->inventorySize > MAX_INVENTORY) {
+ ShowError("Wrong inventorySize field: %d. Must be in range 1 to %d. Character %s (CID: %d, AID: %d)\n",
+ p->inventorySize, MAX_INVENTORY, p->name, p->char_id, p->account_id);
+ Assert_report(0);
+ p->inventorySize = FIXED_INVENTORY_SIZE;
+ }
+
strcat(t_msg, " status");
if (!load_everything) // For quick selection of data when displaying the char menu
@@ -1170,11 +1332,11 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
//`memo` (`memo_id`,`char_id`,`map`,`x`,`y`)
memset(&tmp_point, 0, sizeof(tmp_point));
if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", memo_db, MAX_MEMOPOINTS)
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &point_map, sizeof(point_map), NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &tmp_point.x, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &tmp_point.y, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &point_map, sizeof point_map, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT16, &tmp_point.x, sizeof tmp_point.x, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT16, &tmp_point.y, sizeof tmp_point.y, NULL, NULL)
)
SqlStmt_ShowDebug(stmt);
@@ -1184,86 +1346,23 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
}
strcat(t_msg, " memo");
- //read inventory
- //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `expire_time`, `favorite`, `bound`, `unique_id`)
- StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`");
- for( i = 0; i < MAX_SLOTS; ++i )
- StrBuf->Printf(&buf, ", `card%d`", i);
- StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY);
+ /* read inventory [Smokexyz/Hercules] */
+ if (chr->getitemdata_from_sql(p->inventory, MAX_INVENTORY, p->char_id, TABLE_INVENTORY) > 0)
+ strcat(t_msg, " inventory");
- memset(&tmp_item, 0, sizeof(tmp_item));
- if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
- || SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_CHAR, &tmp_item.favorite, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_UCHAR, &tmp_item.bound, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_UINT64, &tmp_item.unique_id, 0, NULL, NULL)
- )
- SqlStmt_ShowDebug(stmt);
- for( i = 0; i < MAX_SLOTS; ++i )
- if( SQL_ERROR == SQL->StmtBindColumn(stmt, 11+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
- SqlStmt_ShowDebug(stmt);
-
- for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i )
- memcpy(&p->inventory[i], &tmp_item, sizeof(tmp_item));
-
- strcat(t_msg, " inventory");
-
- //read cart
- //`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, expire_time`, `bound`, `unique_id`)
- StrBuf->Clear(&buf);
- StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
- for( j = 0; j < MAX_SLOTS; ++j )
- StrBuf->Printf(&buf, ", `card%d`", j);
- StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART);
-
- memset(&tmp_item, 0, sizeof(tmp_item));
- if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
- || SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &tmp_item.equip, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &tmp_item.bound, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &tmp_item.unique_id, 0, NULL, NULL)
- ) {
- SqlStmt_ShowDebug(stmt);
- }
- for( i = 0; i < MAX_SLOTS; ++i )
- if( SQL_ERROR == SQL->StmtBindColumn(stmt, 10+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) )
- SqlStmt_ShowDebug(stmt);
-
- for( i = 0; i < MAX_CART && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i )
- memcpy(&p->cart[i], &tmp_item, sizeof(tmp_item));
- strcat(t_msg, " cart");
-
- //read storage
- inter_storage->fromsql(p->account_id, &p->storage);
- strcat(t_msg, " storage");
+ /* read cart [Smokexyz/Hercules] */
+ if (chr->getitemdata_from_sql(p->cart, MAX_CART, p->char_id, TABLE_CART) > 0)
+ strcat(t_msg, " cart");
//read skill
//`skill` (`char_id`, `id`, `lv`)
memset(&tmp_skill, 0, sizeof(tmp_skill));
- if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL)
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL_DB)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id , 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UCHAR , &tmp_skill.lv , 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UCHAR , &tmp_skill.flag, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id, sizeof tmp_skill.id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UCHAR, &tmp_skill.lv, sizeof tmp_skill.lv, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UCHAR, &tmp_skill.flag, sizeof tmp_skill.flag, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
}
@@ -1271,7 +1370,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
if( tmp_skill.flag != SKILL_FLAG_PERM_GRANTED )
tmp_skill.flag = SKILL_FLAG_PERMANENT;
- for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i ) {
+ for (i = 0; i < MAX_SKILL_DB && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i) {
if( skillid2idx[tmp_skill.id] )
memcpy(&p->skill[skillid2idx[tmp_skill.id]], &tmp_skill, sizeof(tmp_skill));
else
@@ -1283,11 +1382,11 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
//`friends` (`char_id`, `friend_account`, `friend_id`)
memset(&tmp_friend, 0, sizeof(tmp_friend));
if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", char_db, friend_db, MAX_FRIENDS)
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_friend.account_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &tmp_friend.char_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &tmp_friend.name, sizeof(tmp_friend.name), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_friend.account_id, sizeof tmp_friend.account_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &tmp_friend.char_id, sizeof tmp_friend.char_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &tmp_friend.name, sizeof tmp_friend.name, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
}
@@ -1301,13 +1400,15 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
//`hotkey` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`
memset(&tmp_hotkey, 0, sizeof(tmp_hotkey));
if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", hotkey_db)
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &hotkey_num, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UCHAR, &tmp_hotkey.type, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &tmp_hotkey.id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &tmp_hotkey.lv, 0, NULL, NULL) )
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &hotkey_num, sizeof hotkey_num, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UCHAR, &tmp_hotkey.type, sizeof tmp_hotkey.type, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &tmp_hotkey.id, sizeof tmp_hotkey.id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &tmp_hotkey.lv, sizeof tmp_hotkey.lv, NULL, NULL)
+ ) {
SqlStmt_ShowDebug(stmt);
+ }
while( SQL_SUCCESS == SQL->StmtNextRow(stmt) )
{
@@ -1328,12 +1429,12 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
//`account_data` (`account_id`,`bank_vault`,`base_exp`,`base_drop`,`base_death`)
if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `bank_vault`,`base_exp`,`base_drop`,`base_death` FROM `%s` WHERE `account_id`=? LIMIT 1", account_data_db)
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &account_id, 0)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &account_id, sizeof account_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p->bank_vault, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_USHORT, &p->mod_exp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_USHORT, &p->mod_drop, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &p->mod_death, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p->bank_vault, sizeof p->bank_vault, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_USHORT, &p->mod_exp, sizeof p->mod_exp, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_USHORT, &p->mod_drop, sizeof p->mod_drop, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &p->mod_death, sizeof p->mod_death, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
}
@@ -1344,7 +1445,6 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
if (chr->show_save_log)
ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfully!
SQL->StmtFree(stmt);
- StrBuf->Destroy(&buf);
/* load options into proper vars */
if( opt & OPT_ALLOW_PARTY )
@@ -1358,7 +1458,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
}
//==========================================================================================================
-int char_mmo_char_sql_init(void)
+static int char_mmo_char_sql_init(void)
{
chr->char_db_= idb_alloc(DB_OPT_RELEASE_DATA);
@@ -1375,7 +1475,8 @@ int char_mmo_char_sql_init(void)
}
/* [Ind/Hercules] - special thanks to Yommy for providing the packet structure/data */
-bool char_char_slotchange(struct char_session_data *sd, int fd, unsigned short from, unsigned short to) {
+static bool char_char_slotchange(struct char_session_data *sd, int fd, unsigned short from, unsigned short to)
+{
struct mmo_charstatus char_dat;
int from_id = 0;
@@ -1427,7 +1528,7 @@ bool char_char_slotchange(struct char_session_data *sd, int fd, unsigned short f
//-----------------------------------
// Function to change character's names
//-----------------------------------
-int char_rename_char_sql(struct char_session_data *sd, int char_id)
+static int char_rename_char_sql(struct char_session_data *sd, int char_id)
{
struct mmo_charstatus char_dat;
char esc_name[NAME_LENGTH*2+1];
@@ -1446,6 +1547,14 @@ int char_rename_char_sql(struct char_session_data *sd, int char_id)
if( char_dat.rename == 0 )
return 1;
+ if (char_aegis_rename) {
+ if (char_dat.guild_id > 0) {
+ return 5; // MSG_FAILED_RENAME_BELONGS_TO_GUILD
+ } else if (char_dat.party_id > 0) {
+ return 6; // MSG_FAILED_RENAME_BELONGS_TO_PARTY
+ }
+ }
+
SQL->EscapeStringLen(inter->sql_handle, esc_name, sd->new_name, strnlen(sd->new_name, NAME_LENGTH));
// check if the char exist
@@ -1471,21 +1580,76 @@ int char_rename_char_sql(struct char_session_data *sd, int char_id)
// log change
if (chr->enable_logs) {
if (SQL_ERROR == SQL->Query(inter->sql_handle,
- "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)"
- "VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')",
- charlog_db, "change char name", sd->account_id, char_dat.char_id, char_dat.slot, esc_name))
+ "INSERT INTO `%s` ("
+ " `time`, `char_msg`, `account_id`, `char_id`, `char_num`, `class`, `name`,"
+ " `str`, `agi`, `vit`, `int`, `dex`, `luk`,"
+ " `hair`, `hair_color`"
+ ") VALUES ("
+ " NOW(), 'change char name', '%d', '%d', '%d', '%d', '%s',"
+ " '%d', '%d', '%d', '%d', '%d', '%d',"
+ " '%d', '%d'"
+ ")",
+ charlog_db,
+ sd->account_id, char_dat.char_id, char_dat.slot, char_dat.class, esc_name,
+ char_dat.str, char_dat.agi, char_dat.vit, char_dat.int_, char_dat.dex, char_dat.luk,
+ char_dat.hair, char_dat.hair_color
+ ))
Sql_ShowDebug(inter->sql_handle);
}
return 0;
}
-int char_check_char_name(char * name, char * esc_name)
+/**
+ * Checks if the given name exists in the database.
+ *
+ * @param name The name to check.
+ * @param esc_name Escaped version of the name, optional for faster processing.
+ * @retval true if the character name already exists.
+ */
+static bool char_name_exists(const char *name, const char *esc_name)
+{
+ char esc_name2[NAME_LENGTH * 2 + 1];
+
+ nullpo_retr(true, name);
+
+ if (esc_name == NULL) {
+ SQL->EscapeStringLen(inter->sql_handle, esc_name2, name, strnlen(name, NAME_LENGTH));
+ esc_name = esc_name2;
+ }
+
+ if (name_ignoring_case) {
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name)) {
+ Sql_ShowDebug(inter->sql_handle);
+ return true;
+ }
+ } else {
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name)) {
+ Sql_ShowDebug(inter->sql_handle);
+ return true;
+ }
+ }
+ if (SQL->NumRows(inter->sql_handle) > 0)
+ return true;
+
+ return false;
+}
+
+/**
+ * Checks if the given name is valid for a new character.
+ *
+ * @param name The name to check.
+ * @param esc_name Escaped version of the name, optional for faster processing.
+ * @retval 0 if the name is valid.
+ * @retval -1 if the name already exists or is reserved
+ * @retval -2 if the name is too short or contains special characters.
+ * @retval -5 if the name contains forbidden characters.
+ */
+static int char_check_char_name(const char *name, const char *esc_name)
{
int i;
nullpo_retr(-2, name);
- nullpo_retr(-2, esc_name);
// check length of character name
if (name[0] == '\0')
@@ -1496,9 +1660,16 @@ int char_check_char_name(char * name, char * esc_name)
**/
if( strlen( name ) < 4 )
return -2;
- // check content of character name
- if( remove_control_chars(name) )
- return -2; // control chars in name
+
+ {
+ // check content of character name
+ char *name_copy = aStrdup(name);
+ if (remove_control_chars(name_copy)) {
+ aFree(name_copy);
+ return -2; // control chars in name
+ }
+ aFree(name_copy);
+ }
// check for reserved names
if( strcmpi(name, wisp_server_name) == 0 )
@@ -1517,19 +1688,9 @@ int char_check_char_name(char * name, char * esc_name)
if( strchr(char_name_letters, name[i]) != NULL )
return -5;
}
- if( name_ignoring_case ) {
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name) ) {
- Sql_ShowDebug(inter->sql_handle);
- return -2;
- }
- } else {
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name) ) {
- Sql_ShowDebug(inter->sql_handle);
- return -2;
- }
- }
- if( SQL->NumRows(inter->sql_handle) > 0 )
- return -1; // name already exists
+
+ if (chr->name_exists(name, esc_name))
+ return -1;
return 0;
}
@@ -1544,7 +1705,7 @@ int char_check_char_name(char * name, char * esc_name)
* -5: 'Symbols in Character Names are forbidden'
* char_id: Success
**/
-int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, int16 starting_class)
+static int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, int16 starting_class, uint8 sex)
{
char name[NAME_LENGTH];
char esc_name[NAME_LENGTH*2+1];
@@ -1565,7 +1726,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
@@ -1587,17 +1748,17 @@ int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int
if( sd->found_char[slot] != -1 )
return -2; /* character account limit exceeded */
+
#if PACKETVER >= 20120307
// Insert the new char entry to the database
if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `class`, `zeny`, `status_point`,`str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`,"
- "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
- "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')",
+ "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`, `sex`) VALUES ("
+ "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%c')",
char_db, sd->account_id , slot, esc_name, starting_class, start_zeny, 48, str, agi, vit, int_, dex, luk,
(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ), (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
- mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) )
- {
- Sql_ShowDebug(inter->sql_handle);
- return -2; //No, stop the procedure!
+ mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y, sex)) {
+ Sql_ShowDebug(inter->sql_handle);
+ return -2; //No, stop the procedure!
}
#else
//Insert the new char entry to the database
@@ -1647,14 +1808,14 @@ int char_make_new_char_sql(struct char_session_data *sd, const char *name_, int
}
}
- ShowInfo("Created char: account: %d, char: %d, slot: %d, name: %s\n", sd->account_id, char_id, slot, name);
+ ShowInfo("Created char: account: %d, char: %d, slot: %d, name: %s, sex: %c\n", sd->account_id, char_id, slot, name, sex);
return char_id;
}
/*----------------------------------------------------------------------------------------------------------*/
/* Divorce Players */
/*----------------------------------------------------------------------------------------------------------*/
-int char_divorce_char_sql(int partner_id1, int partner_id2)
+static int char_divorce_char_sql(int partner_id1, int partner_id2)
{
unsigned char buf[64];
@@ -1677,7 +1838,7 @@ int char_divorce_char_sql(int partner_id1, int partner_id2)
/* Returns 0 if successful
* Returns < 0 for error
*/
-int char_delete_char_sql(int char_id)
+static int char_delete_char_sql(int char_id)
{
char name[NAME_LENGTH];
char esc_name[NAME_LENGTH*2+1]; //Name needs be escaped.
@@ -1757,11 +1918,11 @@ int char_delete_char_sql(int char_id)
/* remove homunculus */
if( hom_id )
- mapif->homunculus_delete(hom_id);
+ inter_homunculus->delete(hom_id);
/* remove elemental */
if (elemental_id)
- mapif->elemental_delete(elemental_id);
+ inter_elemental->delete(elemental_id);
/* remove mercenary data */
inter_mercenary->owner_delete(char_id);
@@ -1833,16 +1994,16 @@ int char_delete_char_sql(int char_id)
if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", guild_db, char_id) )
Sql_ShowDebug(inter->sql_handle);
else if( SQL->NumRows(inter->sql_handle) > 0 )
- mapif->parse_BreakGuild(0,guild_id);
+ inter_guild->disband(guild_id);
else if( guild_id )
- inter_guild->leave(guild_id, account_id, char_id);// Leave your guild.
+ inter_guild->leave(guild_id, account_id, char_id, 0, "** Character Deleted **", -1);// Leave your guild.
return 0;
}
//---------------------------------------------------------------------
// This function return the number of online players in all map-servers
//---------------------------------------------------------------------
-int char_count_users(void)
+static int char_count_users(void)
{
int i, users;
@@ -1858,8 +2019,9 @@ int char_count_users(void)
// Writes char data to the buffer in the format used by the client.
// Used in packets 0x6b (chars info) and 0x6d (new char info)
// Returns the size
-#define MAX_CHAR_BUF 150 //Max size (for WFIFOHEAD calls)
-int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
+#define MAX_CHAR_BUF (PACKET_LEN_0x006d - 2)
+static int char_mmo_char_tobuf(uint8 *buffer, struct mmo_charstatus *p)
+{
unsigned short offset = 0;
uint8* buf;
@@ -1867,10 +2029,23 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
return 0;
buf = WBUFP(buffer,0);
+
WBUFL(buf,0) = p->char_id;
- WBUFL(buf,4) = min(p->base_exp, INT32_MAX);
+#if PACKETVER >= 20170830
+ WBUFQ(buf,4) = min(p->base_exp, INT64_MAX);
+ offset += 4;
+ buf = WBUFP(buffer, offset);
+#else
+ WBUFL(buf,4) = min((uint32)(p->base_exp), INT32_MAX);
+#endif
WBUFL(buf,8) = p->zeny;
- WBUFL(buf,12) = min(p->job_exp, INT32_MAX);
+#if PACKETVER >= 20170830
+ WBUFQ(buf,12) = min(p->job_exp, INT64_MAX);
+ offset += 4;
+ buf = WBUFP(buffer, offset);
+#else
+ WBUFL(buf,12) = min((uint32)(p->job_exp), INT32_MAX);
+#endif
WBUFL(buf,16) = p->job_level;
WBUFL(buf,20) = 0; // probably opt1
WBUFL(buf,24) = 0; // probably opt2
@@ -1900,14 +2075,14 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
//When the weapon is sent and your option is riding, the client crashes on login!?
// FIXME[Haru]: is OPTION_HANBOK intended to be part of this list? And if it is, should the list also include other OPTION_ costumes?
- WBUFW(buf,56) = (p->option&(OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_HANBOK)) ? 0 : p->weapon;
+ WBUFW(buf,56) = (p->option&(OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_HANBOK)) ? 0 : p->look.weapon;
WBUFW(buf,58) = p->base_level;
WBUFW(buf,60) = min(p->skill_point, INT16_MAX);
- WBUFW(buf,62) = p->head_bottom;
- WBUFW(buf,64) = p->shield;
- WBUFW(buf,66) = p->head_top;
- WBUFW(buf,68) = p->head_mid;
+ WBUFW(buf,62) = p->look.head_bottom;
+ WBUFW(buf,64) = p->look.shield;
+ WBUFW(buf,66) = p->look.head_top;
+ WBUFW(buf,68) = p->look.head_mid;
WBUFW(buf,70) = p->hair_color;
WBUFW(buf,72) = p->clothes_color;
memcpy(WBUFP(buf,74), p->name, NAME_LENGTH);
@@ -1931,7 +2106,7 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
offset += 4;
#endif
#if PACKETVER >= 20110111
- WBUFL(buf,128) = p->robe;
+ WBUFL(buf,128) = p->look.robe;
offset += 4;
#endif
#if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity.
@@ -1949,24 +2124,36 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
#endif
#endif
- return 106+offset;
+ if (106 + offset != MAX_CHAR_BUF)
+ Assert_report("Wrong buffer size in char_mmo_char_tobuf");
+ return 106 + offset;
}
/* Made Possible by Yommy~! <3 */
-void char_mmo_char_send099d(int fd, struct char_session_data *sd)
-{
-// support added for client between 20121010 and 20130320
-#if PACKETVER > 20120418
- WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF));
- WFIFOW(fd,0) = 0x99d;
- WFIFOW(fd,2) = chr->mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4;
- WFIFOSET(fd,WFIFOW(fd,2));
+static void char_send_HC_ACK_CHARINFO_PER_PAGE(int fd, struct char_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20130522 || PACKETVER_RE_NUM >= 20130327 || defined(PACKETVER_ZERO)
+ WFIFOHEAD(fd, sizeof(struct PACKET_HC_ACK_CHARINFO_PER_PAGE) + (MAX_CHARS * MAX_CHAR_BUF));
+ struct PACKET_HC_ACK_CHARINFO_PER_PAGE *p = WFIFOP(fd, 0);
+ int count = 0;
+ p->packetId = HEADER_HC_ACK_CHARINFO_PER_PAGE;
+ p->packetLen = chr->mmo_chars_fromsql(sd, WFIFOP(fd, 4), &count) + sizeof(struct PACKET_HC_ACK_CHARINFO_PER_PAGE);
+ WFIFOSET(fd, p->packetLen);
+ // send empty packet if chars count is 3, for trigger final code in client
+ if (count == 3) {
+ WFIFOHEAD(fd, sizeof(struct PACKET_HC_ACK_CHARINFO_PER_PAGE));
+ p = WFIFOP(fd, 0);
+ p->packetId = HEADER_HC_ACK_CHARINFO_PER_PAGE;
+ p->packetLen = sizeof(struct PACKET_HC_ACK_CHARINFO_PER_PAGE);
+ WFIFOSET(fd, p->packetLen);
+ }
#endif
}
/* Sends character ban list */
/* Made Possible by Yommy~! <3 */
-void char_mmo_char_send_ban_list(int fd, struct char_session_data *sd) {
+static void char_mmo_char_send_ban_list(int fd, struct char_session_data *sd)
+{
int i;
time_t now = time(NULL);
@@ -2006,23 +2193,27 @@ void char_mmo_char_send_ban_list(int fd, struct char_session_data *sd) {
//----------------------------------------
// [Ind/Hercules] notify client about charselect window data
//----------------------------------------
-void char_mmo_char_send_slots_info(int fd, struct char_session_data* sd) {
+static void char_mmo_char_send_slots_info(int fd, struct char_session_data *sd)
+{
+// also probably supported client 2013-02-15aRagexe but not 2013-02-15bRagexe [4144]
+#if PACKETVER_MAIN_NUM >= 20130612 || PACKETVER_RE_NUM >= 20130115 || defined(PACKETVER_ZERO)
nullpo_retv(sd);
- WFIFOHEAD(fd,29);
- WFIFOW(fd,0) = 0x82d;
- WFIFOW(fd,2) = 29;
- WFIFOB(fd,4) = sd->char_slots;
- WFIFOB(fd,5) = MAX_CHARS - sd->char_slots;
- WFIFOB(fd,6) = 0;
- WFIFOB(fd,7) = sd->char_slots;
- WFIFOB(fd,8) = sd->char_slots;
- memset(WFIFOP(fd,9), 0, 20); // unused bytes
- WFIFOSET(fd,29);
+ WFIFOHEAD(fd, 29);
+ WFIFOW(fd, 0) = 0x82d;
+ WFIFOW(fd, 2) = 29;
+ WFIFOB(fd, 4) = sd->char_slots;
+ WFIFOB(fd, 5) = MAX_CHARS - sd->char_slots;
+ WFIFOB(fd, 6) = 0;
+ WFIFOB(fd, 7) = sd->char_slots;
+ WFIFOB(fd, 8) = sd->char_slots;
+ memset(WFIFOP(fd, 9), 0, 20); // unused bytes
+ WFIFOSET(fd, 29);
+#endif
}
//----------------------------------------
// Function to send characters to a player
//----------------------------------------
-int char_mmo_char_send_characters(int fd, struct char_session_data* sd)
+static int char_mmo_char_send_characters(int fd, struct char_session_data *sd)
{
int j, offset = 0;
nullpo_ret(sd);
@@ -2041,14 +2232,14 @@ int char_mmo_char_send_characters(int fd, struct char_session_data* sd)
WFIFOB(fd,6) = MAX_CHARS; // Premium slots. AKA any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red
#endif
memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes
- j+=chr->mmo_chars_fromsql(sd, WFIFOP(fd,j));
+ j += chr->mmo_chars_fromsql(sd, WFIFOP(fd, j), NULL);
WFIFOW(fd,2) = j; // packet len
WFIFOSET(fd,j);
return 0;
}
-int char_char_married(int pl1, int pl2)
+static int char_char_married(int pl1, int pl2)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1) )
Sql_ShowDebug(inter->sql_handle);
@@ -2067,7 +2258,7 @@ int char_char_married(int pl1, int pl2)
return 0;
}
-int char_char_child(int parent_id, int child_id)
+static int char_char_child(int parent_id, int child_id)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id) )
Sql_ShowDebug(inter->sql_handle);
@@ -2086,7 +2277,7 @@ int char_char_child(int parent_id, int child_id)
return 0;
}
-int char_char_family(int cid1, int cid2, int cid3)
+static int char_char_family(int cid1, int cid2, int cid3)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, cid1, cid2, cid3) )
Sql_ShowDebug(inter->sql_handle);
@@ -2116,7 +2307,7 @@ int char_char_family(int cid1, int cid2, int cid3)
//----------------------------------------------------------------------
// Force disconnection of an online player (with account value) by [Yor]
//----------------------------------------------------------------------
-void char_disconnect_player(int account_id)
+static void char_disconnect_player(int account_id)
{
int i;
struct char_session_data* sd;
@@ -2127,7 +2318,7 @@ void char_disconnect_player(int account_id)
sockt->eof(i);
}
-void char_authfail_fd(int fd, int type)
+static void char_authfail_fd(int fd, int type)
{
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x81;
@@ -2135,7 +2326,7 @@ void char_authfail_fd(int fd, int type)
WFIFOSET(fd,3);
}
-void char_request_account_data(int account_id)
+static void char_request_account_data(int account_id)
{
WFIFOHEAD(chr->login_fd,6);
WFIFOW(chr->login_fd,0) = 0x2716;
@@ -2181,21 +2372,21 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
// continues when account data is received...
}
-void char_ping_login_server(int fd)
+static void char_ping_login_server(int fd)
{
WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718)
WFIFOW(fd,0) = 0x2719;
WFIFOSET(fd,2);
}
-int char_parse_fromlogin_connection_state(int fd)
+static int char_parse_fromlogin_connection_state(int fd)
{
if (RFIFOB(fd,2)) {
//printf("connect login server error : %d\n", RFIFOB(fd,2));
ShowError("Can not connect to login-server.\n");
ShowError("The server communication passwords (default s1/p1) are probably invalid.\n");
ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n");
- ShowError("The communication passwords are set in /conf/map-server.conf and /conf/char/char-server.conf\n");
+ ShowError("The communication passwords are set in /conf/map/map-server.conf and /conf/char/char-server.conf\n");
sockt->eof(fd);
return 1;
} else {
@@ -2208,7 +2399,7 @@ int char_parse_fromlogin_connection_state(int fd)
// 0 - rejected from server
//
-void char_auth_error(int fd, unsigned char flag)
+static void char_auth_error(int fd, unsigned char flag)
{
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x6c;
@@ -2216,7 +2407,7 @@ void char_auth_error(int fd, unsigned char flag)
WFIFOSET(fd,3);
}
-void char_parse_fromlogin_auth_state(int fd)
+static void char_parse_fromlogin_auth_state(int fd)
{
struct char_session_data* sd = NULL;
int account_id = RFIFOL(fd,2);
@@ -2258,7 +2449,7 @@ void char_parse_fromlogin_auth_state(int fd)
}
}
-void char_parse_fromlogin_account_data(int fd)
+static void char_parse_fromlogin_account_data(int fd)
{
struct char_session_data* sd = (struct char_session_data*)sockt->session[fd]->session_data;
int i;
@@ -2284,12 +2475,8 @@ void char_parse_fromlogin_account_data(int fd)
chr->auth_error(i, 0);
} else {
// send characters to player
- #if PACKETVER >= 20130000
chr->mmo_char_send_slots_info(i, sd);
chr->mmo_char_send_characters(i, sd);
- #else
- chr->mmo_char_send_characters(i, sd);
- #endif
#if PACKETVER >= 20060819
chr->mmo_char_send_ban_list(i, sd);
#endif
@@ -2301,14 +2488,14 @@ void char_parse_fromlogin_account_data(int fd)
RFIFOSKIP(fd,72);
}
-void char_parse_fromlogin_login_pong(int fd)
+static void char_parse_fromlogin_login_pong(int fd)
{
RFIFOSKIP(fd,2);
if (sockt->session[fd])
sockt->session[fd]->flag.ping = 0;
}
-void char_changesex(int account_id, int sex)
+static void char_changesex(int account_id, int sex)
{
unsigned char buf[7];
@@ -2329,7 +2516,7 @@ void char_changesex(int account_id, int sex)
* @param class The character's current job class.
* @param guild_id The character's guild ID.
*/
-void char_change_sex_sub(int sex, int acc, int char_id, int class, int guild_id)
+static void char_change_sex_sub(int sex, int acc, int char_id, int class, int guild_id)
{
// job modification
if (class == JOB_BARD || class == JOB_DANCER)
@@ -2358,7 +2545,7 @@ void char_change_sex_sub(int sex, int acc, int char_id, int class, int guild_id)
inter_guild->sex_changed(guild_id, acc, char_id, sex);
}
-int char_parse_fromlogin_changesex_reply(int fd)
+static int char_parse_fromlogin_changesex_reply(int fd)
{
int char_id = 0, class = 0, guild_id = 0;
int i;
@@ -2384,13 +2571,13 @@ int char_parse_fromlogin_changesex_reply(int fd)
stmt = SQL->StmtMalloc(inter->sql_handle);
if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc)
|| SQL_ERROR == SQL->StmtExecute(stmt)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &char_id, sizeof char_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &class, sizeof class, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &guild_id, sizeof guild_id, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
}
- SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &char_id, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &class, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &guild_id, 0, NULL, NULL);
for (i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i) {
char_change_sex_sub(sex, acc, char_id, class, guild_id);
@@ -2405,25 +2592,14 @@ int char_parse_fromlogin_changesex_reply(int fd)
return 0;
}
-void char_parse_fromlogin_account_reg2(int fd)
+static void char_parse_fromlogin_account_reg2(int fd)
{
//Receive account_reg2 registry, forward to map servers.
mapif->sendall(RFIFOP(fd, 0), RFIFOW(fd,2));
RFIFOSKIP(fd, RFIFOW(fd,2));
}
-void mapif_ban(int id, unsigned int flag, int status)
-{
- // send to all map-servers to disconnect the player
- unsigned char buf[11];
- WBUFW(buf,0) = 0x2b14;
- WBUFL(buf,2) = id;
- WBUFB(buf,6) = flag; // 0: change of status, 1: ban
- WBUFL(buf,7) = status; // status or final date of a banishment
- mapif->sendall(buf, 11);
-}
-
-void char_parse_fromlogin_ban(int fd)
+static void char_parse_fromlogin_ban(int fd)
{
mapif->ban(RFIFOL(fd,2), RFIFOB(fd,6), RFIFOL(fd,7));
// disconnect player if online on char-server
@@ -2431,7 +2607,7 @@ void char_parse_fromlogin_ban(int fd)
RFIFOSKIP(fd,11);
}
-void char_parse_fromlogin_kick(int fd)
+static void char_parse_fromlogin_kick(int fd)
{
int aid = RFIFOL(fd,2);
struct online_char_data* character = (struct online_char_data*)idb_get(chr->online_char_db, aid);
@@ -2461,7 +2637,7 @@ void char_parse_fromlogin_kick(int fd)
idb_remove(auth_db, aid);// reject auth attempts from map-server
}
-void char_update_ip(int fd)
+static void char_update_ip(int fd)
{
WFIFOHEAD(fd,6);
WFIFOW(fd,0) = 0x2736;
@@ -2469,7 +2645,7 @@ void char_update_ip(int fd)
WFIFOSET(fd,6);
}
-void char_parse_fromlogin_update_ip(int fd)
+static void char_parse_fromlogin_update_ip(int fd)
{
unsigned char buf[2];
uint32 new_ip = 0;
@@ -2492,22 +2668,23 @@ void char_parse_fromlogin_update_ip(int fd)
RFIFOSKIP(fd,2);
}
-void char_parse_fromlogin_accinfo2_failed(int fd)
+static void char_parse_fromlogin_accinfo2_failed(int fd)
{
- mapif->parse_accinfo2(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14),
+ inter->accinfo2(false, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14),
NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, 0, 0);
RFIFOSKIP(fd,18);
}
-void char_parse_fromlogin_accinfo2_ok(int fd)
+static void char_parse_fromlogin_accinfo2_ok(int fd)
{
- mapif->parse_accinfo2(true, RFIFOL(fd,167), RFIFOL(fd,171), RFIFOL(fd,175), RFIFOL(fd,179),
+ inter->accinfo2(true, RFIFOL(fd,167), RFIFOL(fd,171), RFIFOL(fd,175), RFIFOL(fd,179),
RFIFOP(fd,2), RFIFOP(fd,26), RFIFOP(fd,59), RFIFOP(fd,99), RFIFOP(fd,119),
RFIFOP(fd,151), RFIFOP(fd,156), RFIFOL(fd,115), RFIFOL(fd,143), RFIFOL(fd,147));
RFIFOSKIP(fd,183);
}
-int char_parse_fromlogin(int fd) {
+static int char_parse_fromlogin(int fd)
+{
// only process data from the login-server
if( fd != chr->login_fd ) {
ShowDebug("chr->parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
@@ -2639,7 +2816,7 @@ int char_parse_fromlogin(int fd) {
return 0;
}
-int char_request_accreg2(int account_id, int char_id)
+static int char_request_accreg2(int account_id, int char_id)
{
if (chr->login_fd > 0) {
WFIFOHEAD(chr->login_fd,10);
@@ -2655,7 +2832,8 @@ int char_request_accreg2(int account_id, int char_id)
/**
* Handles global account reg saving that continues with chr->global_accreg_to_login_add and global_accreg_to_send
**/
-void char_global_accreg_to_login_start (int account_id, int char_id) {
+static void char_global_accreg_to_login_start(int account_id, int char_id)
+{
WFIFOHEAD(chr->login_fd, 60000 + 300);
WFIFOW(chr->login_fd,0) = 0x2728;
WFIFOW(chr->login_fd,2) = 14;
@@ -2667,14 +2845,16 @@ void char_global_accreg_to_login_start (int account_id, int char_id) {
/**
* Completes global account reg saving that starts chr->global_accreg_to_login_start and continues with chr->global_accreg_to_login_add
**/
-void char_global_accreg_to_login_send (void) {
+static void char_global_accreg_to_login_send(void)
+{
WFIFOSET(chr->login_fd, WFIFOW(chr->login_fd,2));
}
/**
* Handles global account reg saving that starts chr->global_accreg_to_login_start and ends with global_accreg_to_send
**/
-void char_global_accreg_to_login_add (const char *key, unsigned int index, intptr_t val, bool is_string) {
+static void char_global_accreg_to_login_add(const char *key, unsigned int index, intptr_t val, bool is_string)
+{
int nlen = WFIFOW(chr->login_fd, 2);
size_t len = strlen(key)+1;
@@ -2721,7 +2901,8 @@ void char_global_accreg_to_login_add (const char *key, unsigned int index, intpt
}
}
-void char_read_fame_list(void) {
+static void char_read_fame_list(void)
+{
int i;
char* data;
size_t len;
@@ -2779,7 +2960,8 @@ void char_read_fame_list(void) {
}
// Send map-servers the fame ranking lists
-int char_send_fame_list(int fd) {
+static int char_send_fame_list(int fd)
+{
int i, len = 8;
unsigned char buf[32000];
@@ -2814,7 +2996,8 @@ int char_send_fame_list(int fd) {
return 0;
}
-void char_update_fame_list(int type, int index, int fame) {
+static void char_update_fame_list(int type, int index, int fame)
+{
unsigned char buf[8];
WBUFW(buf,0) = 0x2b22;
WBUFB(buf,2) = type;
@@ -2825,7 +3008,7 @@ void char_update_fame_list(int type, int index, int fame) {
//Loads a character's name and stores it in the buffer given (must be NAME_LENGTH in size) and not NULL
//Returns 1 on found, 0 on not found (buffer is filled with Unknown char name)
-int char_loadName(int char_id, char* name)
+static int char_loadName(int char_id, char *name)
{
char* data;
size_t len;
@@ -2845,77 +3028,13 @@ int char_loadName(int char_id, char* name)
return 0;
}
-/// Initializes a server structure.
-void mapif_server_init(int id)
-{
- //memset(&chr->server[id], 0, sizeof(server[id]));
- chr->server[id].fd = -1;
-}
-
-/// Destroys a server structure.
-void mapif_server_destroy(int id)
-{
- if( chr->server[id].fd == -1 )
- {
- sockt->close(chr->server[id].fd);
- chr->server[id].fd = -1;
- }
-}
-
-
-/// Resets all the data related to a server.
-void mapif_server_reset(int id)
-{
- int i,j;
- unsigned char buf[16384];
- int fd = chr->server[id].fd;
- //Notify other map servers that this one is gone. [Skotlex]
- WBUFW(buf,0) = 0x2b20;
- WBUFL(buf,4) = htonl(chr->server[id].ip);
- WBUFW(buf,8) = htons(chr->server[id].port);
- j = 0;
- for (i = 0; i < VECTOR_LENGTH(chr->server[id].maps); i++) {
- uint16 m = VECTOR_INDEX(chr->server[id].maps, i);
- if (m != 0)
- WBUFW(buf,10+(j++)*4) = m;
- }
- if (j > 0) {
- WBUFW(buf,2) = j * 4 + 10;
- mapif->sendallwos(fd, buf, WBUFW(buf,2));
- }
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", ragsrvinfo_db, chr->server[id].fd) )
- Sql_ShowDebug(inter->sql_handle);
- chr->online_char_db->foreach(chr->online_char_db,chr->db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
- mapif->server_destroy(id);
- mapif->server_init(id);
-}
-
-/// Called when the connection to a Map Server is disconnected.
-void mapif_on_disconnect(int id)
-{
- ShowStatus("Map-server #%d has disconnected.\n", id);
- mapif->server_reset(id);
-}
-
-void mapif_on_parse_accinfo(int account_id, int u_fd, int u_aid, int u_group, int map_fd) {
- Assert_retv(chr->login_fd > 0);
- WFIFOHEAD(chr->login_fd,22);
- WFIFOW(chr->login_fd,0) = 0x2740;
- WFIFOL(chr->login_fd,2) = account_id;
- WFIFOL(chr->login_fd,6) = u_fd;
- WFIFOL(chr->login_fd,10) = u_aid;
- WFIFOL(chr->login_fd,14) = u_group;
- WFIFOL(chr->login_fd,18) = map_fd;
- WFIFOSET(chr->login_fd,22);
-}
-
-void char_parse_frommap_datasync(int fd)
+static void char_parse_frommap_datasync(int fd)
{
sockt->datasync(fd, false);
RFIFOSKIP(fd,RFIFOW(fd,2));
}
-void char_parse_frommap_skillid2idx(int fd)
+static void char_parse_frommap_skillid2idx(int fd)
{
int i;
int j = RFIFOW(fd, 2) - 4;
@@ -2924,8 +3043,8 @@ void char_parse_frommap_skillid2idx(int fd)
if( j )
j /= 4;
for(i = 0; i < j; i++) {
- if( RFIFOW(fd, 4 + (i*4)) > MAX_SKILL_ID ) {
- ShowWarning("Error skillid2dx[%d] = %d failed, %d is higher than MAX_SKILL_ID (%d)\n",RFIFOW(fd, 4 + (i*4)), RFIFOW(fd, 6 + (i*4)),RFIFOW(fd, 4 + (i*4)),MAX_SKILL_ID);
+ if (RFIFOW(fd, 4 + (i*4)) >= MAX_SKILL_ID) {
+ ShowWarning("Error skillid2dx[%d] = %d failed, %d is higher than MAX_SKILL_ID (%d)\n", RFIFOW(fd, 4 + (i*4)), RFIFOW(fd, 6 + (i*4)), RFIFOW(fd, 4 + (i*4)), MAX_SKILL_ID);
continue;
}
skillid2idx[RFIFOW(fd, 4 + (i*4))] = RFIFOW(fd, 6 + (i*4));
@@ -2933,7 +3052,7 @@ void char_parse_frommap_skillid2idx(int fd)
RFIFOSKIP(fd, RFIFOW(fd, 2));
}
-void char_map_received_ok(int fd)
+static void char_map_received_ok(int fd)
{
WFIFOHEAD(fd, 3 + NAME_LENGTH);
WFIFOW(fd,0) = 0x2afb;
@@ -2942,7 +3061,7 @@ void char_map_received_ok(int fd)
WFIFOSET(fd,3+NAME_LENGTH);
}
-void char_send_maps(int fd, int id, int j)
+static void char_send_maps(int fd, int id, int j)
{
int k,i;
@@ -2979,7 +3098,7 @@ void char_send_maps(int fd, int id, int j)
}
}
-void char_parse_frommap_map_names(int fd, int id)
+static void char_parse_frommap_map_names(int fd, int id)
{
int i;
@@ -3000,7 +3119,7 @@ void char_parse_frommap_map_names(int fd, int id)
RFIFOSKIP(fd,RFIFOW(fd,2));
}
-void char_send_scdata(int fd, int aid, int cid)
+static void char_send_scdata(int fd, int aid, int cid)
{
#ifdef ENABLE_SC_SAVING
if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `type`, `tick`, `val1`, `val2`, `val3`, `val4` "
@@ -3054,7 +3173,7 @@ void char_send_scdata(int fd, int aid, int cid)
#endif
}
-void char_parse_frommap_request_scdata(int fd)
+static void char_parse_frommap_request_scdata(int fd)
{
#ifdef ENABLE_SC_SAVING
int aid = RFIFOL(fd,2);
@@ -3064,7 +3183,7 @@ void char_parse_frommap_request_scdata(int fd)
RFIFOSKIP(fd, 10);
}
-void char_parse_frommap_set_users_count(int fd, int id)
+static void char_parse_frommap_set_users_count(int fd, int id)
{
if (RFIFOW(fd,2) != chr->server[id].users) {
chr->server[id].users = RFIFOW(fd,2);
@@ -3073,7 +3192,7 @@ void char_parse_frommap_set_users_count(int fd, int id)
RFIFOSKIP(fd, 4);
}
-void char_parse_frommap_set_users(int fd, int id)
+static void char_parse_frommap_set_users(int fd, int id)
{
//TODO: When data mismatches memory, update guild/party online/offline states.
int i;
@@ -3096,7 +3215,7 @@ void char_parse_frommap_set_users(int fd, int id)
RFIFOSKIP(fd,RFIFOW(fd,2));
}
-void char_save_character_ack(int fd, int aid, int cid)
+static void char_save_character_ack(int fd, int aid, int cid)
{
WFIFOHEAD(fd,10);
WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save.
@@ -3105,7 +3224,7 @@ void char_save_character_ack(int fd, int aid, int cid)
WFIFOSET(fd,10);
}
-void char_parse_frommap_save_character(int fd, int id)
+static void char_parse_frommap_save_character(int fd, int id)
{
int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2);
struct online_char_data* character;
@@ -3139,7 +3258,7 @@ void char_parse_frommap_save_character(int fd, int id)
// 0 - not ok
// 1 - ok
-void char_select_ack(int fd, int account_id, uint8 flag)
+static void char_select_ack(int fd, int account_id, uint8 flag)
{
WFIFOHEAD(fd,7);
WFIFOW(fd,0) = 0x2b03;
@@ -3148,7 +3267,7 @@ void char_select_ack(int fd, int account_id, uint8 flag)
WFIFOSET(fd,7);
}
-void char_parse_frommap_char_select_req(int fd)
+static void char_parse_frommap_char_select_req(int fd)
{
int account_id = RFIFOL(fd,2);
uint32 login_id1 = RFIFOL(fd,6);
@@ -3185,7 +3304,7 @@ void char_parse_frommap_char_select_req(int fd)
}
}
-void char_change_map_server_ack(int fd, const uint8 *data, bool ok)
+static void char_change_map_server_ack(int fd, const uint8 *data, bool ok)
{
WFIFOHEAD(fd,30);
WFIFOW(fd,0) = 0x2b06;
@@ -3195,7 +3314,7 @@ void char_change_map_server_ack(int fd, const uint8 *data, bool ok)
WFIFOSET(fd,30);
}
-void char_parse_frommap_change_map_server(int fd)
+static void char_parse_frommap_change_map_server(int fd)
{
int map_id, map_fd = -1;
struct mmo_charstatus* char_data;
@@ -3248,7 +3367,7 @@ void char_parse_frommap_change_map_server(int fd)
RFIFOSKIP(fd,39);
}
-void char_parse_frommap_remove_friend(int fd)
+static void char_parse_frommap_remove_friend(int fd)
{
int char_id = RFIFOL(fd,2);
int friend_id = RFIFOL(fd,6);
@@ -3259,22 +3378,27 @@ void char_parse_frommap_remove_friend(int fd)
RFIFOSKIP(fd,10);
}
-void char_char_name_ack(int fd, int char_id)
+static void char_char_name_ack(int fd, int char_id)
{
WFIFOHEAD(fd,30);
WFIFOW(fd,0) = 0x2b09;
WFIFOL(fd,2) = char_id;
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221 || PACKETVER_ZERO_NUM >= 20180328
+ 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);
}
-void char_parse_frommap_char_name_request(int fd)
+static void char_parse_frommap_char_name_request(int fd)
{
chr->char_name_ack(fd, RFIFOL(fd,2));
RFIFOSKIP(fd,6);
}
-void char_parse_frommap_change_email(int fd)
+static void char_parse_frommap_change_email(int fd)
{
if (chr->login_fd > 0) { // don't send request if no login-server
WFIFOHEAD(chr->login_fd,86);
@@ -3285,17 +3409,7 @@ void char_parse_frommap_change_email(int fd)
RFIFOSKIP(fd, 86);
}
-void mapif_char_ban(int char_id, time_t timestamp)
-{
- unsigned char buf[11];
- WBUFW(buf,0) = 0x2b14;
- WBUFL(buf,2) = char_id;
- WBUFB(buf,6) = 2;
- WBUFL(buf,7) = (unsigned int)timestamp;
- mapif->sendall(buf, 11);
-}
-
-void char_ban(int account_id, int char_id, time_t *unban_time, short year, short month, short day, short hour, short minute, short second)
+static void char_ban(int account_id, int char_id, time_t *unban_time, short year, short month, short day, short hour, short minute, short second)
{
time_t timestamp;
struct tm *tmtime;
@@ -3320,8 +3434,8 @@ void char_ban(int account_id, int char_id, time_t *unban_time, short year, short
if( SQL_SUCCESS != SQL->StmtPrepare(stmt,
"UPDATE `%s` SET `unban_time` = ? WHERE `char_id` = ? LIMIT 1",
char_db)
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_LONG, &timestamp, sizeof(timestamp))
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_INT, &char_id, sizeof(char_id))
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_TIME, &timestamp, sizeof timestamp)
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_SUCCESS != SQL->StmtExecute(stmt)
) {
SqlStmt_ShowDebug(stmt);
@@ -3330,14 +3444,14 @@ void char_ban(int account_id, int char_id, time_t *unban_time, short year, short
SQL->StmtFree(stmt);
// condition applies; send to all map-servers to disconnect the player
- if( timestamp > time(NULL) ) {
+ if (timestamp > time(NULL)) {
mapif->char_ban(char_id, timestamp);
// disconnect player if online on char-server
chr->disconnect_player(account_id);
}
}
-void char_unban(int char_id, int *result)
+static void char_unban(int char_id, int *result)
{
/* handled by char server, so no redirection */
if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `unban_time` = '0' WHERE `char_id` = '%d' LIMIT 1", char_db, char_id) ) {
@@ -3347,7 +3461,7 @@ void char_unban(int char_id, int *result)
}
}
-void char_ask_name_ack(int fd, int acc, const char* name, int type, int result)
+static void char_ask_name_ack(int fd, int acc, const char *name, int type, int result)
{
nullpo_retv(name);
WFIFOHEAD(fd,34);
@@ -3369,7 +3483,7 @@ void char_ask_name_ack(int fd, int acc, const char* name, int type, int result)
* @retval 0 in case of success.
* @retval 1 in case of failure.
*/
-int char_changecharsex(int char_id, int sex)
+static int char_changecharsex(int char_id, int sex)
{
int class = 0, guild_id = 0, account_id = 0;
char *data;
@@ -3402,7 +3516,7 @@ int char_changecharsex(int char_id, int sex)
return 0;
}
-void char_parse_frommap_change_account(int fd)
+static void char_parse_frommap_change_account(int fd)
{
int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline
char esc_name[NAME_LENGTH*2+1];
@@ -3488,7 +3602,7 @@ void char_parse_frommap_change_account(int fd)
}
}
-void char_parse_frommap_fame_list(int fd)
+static void char_parse_frommap_fame_list(int fd)
{
int cid = RFIFOL(fd, 2);
int fame = RFIFOL(fd, 6);
@@ -3539,13 +3653,13 @@ void char_parse_frommap_fame_list(int fd)
RFIFOSKIP(fd,11);
}
-void char_parse_frommap_divorce_char(int fd)
+static void char_parse_frommap_divorce_char(int fd)
{
chr->divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6));
RFIFOSKIP(fd,10);
}
-void char_parse_frommap_ragsrvinfo(int fd)
+static void char_parse_frommap_ragsrvinfo(int fd)
{
char esc_server_name[sizeof(chr->server_name)*2+1];
@@ -3559,32 +3673,32 @@ void char_parse_frommap_ragsrvinfo(int fd)
RFIFOSKIP(fd,14);
}
-void char_parse_frommap_set_char_offline(int fd)
+static void char_parse_frommap_set_char_offline(int fd)
{
chr->set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6));
RFIFOSKIP(fd,10);
}
-void char_parse_frommap_set_all_offline(int fd, int id)
+static void char_parse_frommap_set_all_offline(int fd, int id)
{
chr->set_all_offline(id);
RFIFOSKIP(fd,2);
}
-void char_parse_frommap_set_char_online(int fd, int id)
+static void char_parse_frommap_set_char_online(int fd, int id)
{
chr->set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6));
RFIFOSKIP(fd,10);
}
-void char_parse_frommap_build_fame_list(int fd)
+static void char_parse_frommap_build_fame_list(int fd)
{
chr->read_fame_list();
chr->send_fame_list(-1);
RFIFOSKIP(fd,2);
}
-void char_parse_frommap_save_status_change_data(int fd)
+static void char_parse_frommap_save_status_change_data(int fd)
{
#ifdef ENABLE_SC_SAVING
int aid = RFIFOL(fd, 4);
@@ -3619,20 +3733,20 @@ void char_parse_frommap_save_status_change_data(int fd)
RFIFOSKIP(fd, RFIFOW(fd, 2));
}
-void char_send_pong(int fd)
+static void char_send_pong(int fd)
{
WFIFOHEAD(fd,2);
WFIFOW(fd,0) = 0x2b24;
WFIFOSET(fd,2);
}
-void char_parse_frommap_ping(int fd)
+static void char_parse_frommap_ping(int fd)
{
chr->send_pong(fd);
RFIFOSKIP(fd,2);
}
-void char_map_auth_ok(int fd, int account_id, struct char_auth_node* node, struct mmo_charstatus* cd)
+static void char_map_auth_ok(int fd, int account_id, struct char_auth_node *node, struct mmo_charstatus *cd)
{
nullpo_retv(cd);
WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus));
@@ -3659,7 +3773,7 @@ void char_map_auth_ok(int fd, int account_id, struct char_auth_node* node, struc
WFIFOSET(fd, WFIFOW(fd,2));
}
-void char_map_auth_failed(int fd, int account_id, int char_id, int login_id1, char sex, uint32 ip)
+static void char_map_auth_failed(int fd, int account_id, int char_id, int login_id1, char sex, uint32 ip)
{
WFIFOHEAD(fd,19);
WFIFOW(fd,0) = 0x2b27;
@@ -3671,7 +3785,7 @@ void char_map_auth_failed(int fd, int account_id, int char_id, int login_id1, ch
WFIFOSET(fd,19);
}
-void char_parse_frommap_auth_request(int fd, int id)
+static void char_parse_frommap_auth_request(int fd, int id)
{
struct mmo_charstatus char_dat;
struct char_auth_node* node;
@@ -3724,49 +3838,14 @@ void char_parse_frommap_auth_request(int fd, int id)
}
}
-void char_parse_frommap_update_ip(int fd, int id)
+static void char_parse_frommap_update_ip(int fd, int id)
{
chr->server[id].ip = ntohl(RFIFOL(fd, 2));
ShowInfo("Updated IP address of map-server #%d to %u.%u.%u.%u.\n", id, CONVIP(chr->server[id].ip));
RFIFOSKIP(fd,6);
}
-void char_parse_frommap_request_stats_report(int fd)
-{
- int sfd;/* stat server fd */
- struct hSockOpt opt;
- RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */
-
- opt.silent = 1;
- opt.setTimeo = 1;
-
- if ((sfd = sockt->make_connection(sockt->host2ip("stats.herc.ws"),(uint16)25427,&opt) ) == -1) {
- RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
- RFIFOFLUSH(fd);
- return;/* connection not possible, we drop the report */
- }
-
- sockt->session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */
- sockt->realloc_fifo(sfd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-
- WFIFOHEAD(sfd, RFIFOW(fd,2) );
-
- memcpy(WFIFOP(sfd,0), RFIFOP(fd, 0), RFIFOW(fd,2));
-
- WFIFOSET(sfd, RFIFOW(fd,2) );
-
- do {
- sockt->flush(sfd);
- HSleep(1);
- } while( !sockt->session[sfd]->flag.eof && sockt->session[sfd]->wdata_size );
-
- sockt->close(sfd);
-
- RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */
- RFIFOFLUSH(fd);
-}
-
-void char_parse_frommap_scdata_update(int fd)
+static void char_parse_frommap_scdata_update(int fd)
{
int account_id = RFIFOL(fd, 2);
int char_id = RFIFOL(fd, 6);
@@ -3786,7 +3865,7 @@ void char_parse_frommap_scdata_update(int fd)
RFIFOSKIP(fd, 28);
}
-void char_parse_frommap_scdata_delete(int fd)
+static void char_parse_frommap_scdata_delete(int fd)
{
int account_id = RFIFOL(fd, 2);
int char_id = RFIFOL(fd, 6);
@@ -3800,7 +3879,7 @@ void char_parse_frommap_scdata_delete(int fd)
RFIFOSKIP(fd, 12);
}
-int char_parse_frommap(int fd)
+static int char_parse_frommap(int fd)
{
int id;
@@ -3996,14 +4075,6 @@ int char_parse_frommap(int fd)
chr->parse_frommap_update_ip(fd, id);
break;
- case 0x3008:
- if( RFIFOREST(fd) < RFIFOW(fd,4) )
- return 0;/* packet wasn't fully received yet (still fragmented) */
- else {
- chr->parse_frommap_request_stats_report(fd);
- }
- break;
-
/* individual sc data insertion/update */
case 0x2740:
if( RFIFOREST(fd) < 28 )
@@ -4040,14 +4111,14 @@ int char_parse_frommap(int fd)
return 0;
}
-void do_init_mapif(void)
+static void do_init_mapif(void)
{
int i;
for( i = 0; i < ARRAYLENGTH(chr->server); ++i )
mapif->server_init(i);
}
-void do_final_mapif(void)
+static void do_final_mapif(void)
{
int i;
for( i = 0; i < ARRAYLENGTH(chr->server); ++i )
@@ -4056,7 +4127,7 @@ void do_final_mapif(void)
// Searches for the mapserver that has a given map (and optionally ip/port, if not -1).
// If found, returns the server's index in the 'server' array (otherwise returns -1).
-int char_search_mapserver(unsigned short map, uint32 ip, uint16 port)
+static int char_search_mapserver(unsigned short map, uint32 ip, uint16 port)
{
int i, j;
@@ -4088,7 +4159,7 @@ static int char_mapif_init(int fd)
* @retval 0 if it is a WAN IP.
* @return the appropriate LAN server address to send, if it is a LAN IP.
*/
-uint32 char_lan_subnet_check(uint32 ip)
+static uint32 char_lan_subnet_check(uint32 ip)
{
struct s_subnet lan = {0};
if (sockt->lan_subnet_check(ip, &lan)) {
@@ -4108,7 +4179,7 @@ uint32 char_lan_subnet_check(uint32 ip)
/// 4 (0x71a): To delete a character you must withdraw from the guild.
/// 5 (0x71b): To delete a character you must withdraw from the party.
/// Any (0x718): An unknown error has occurred.
-void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date)
+static void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date)
{// HC: <0828>.W <char id>.L <Msg:0-5>.L <deleteDate>.L
WFIFOHEAD(fd,14);
WFIFOW(fd,0) = 0x828;
@@ -4123,7 +4194,7 @@ void char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_date)
WFIFOSET(fd,14);
}
-void char_delete2_accept_actual_ack(int fd, int char_id, uint32 result)
+static void char_delete2_accept_actual_ack(int fd, int char_id, uint32 result)
{
WFIFOHEAD(fd,10);
WFIFOW(fd,0) = 0x82a;
@@ -4140,12 +4211,12 @@ void char_delete2_accept_actual_ack(int fd, int char_id, uint32 result)
/// 4 (0x71d): Deleting not yet possible time.
/// 5 (0x71e): Date of birth do not match.
/// Any (0x718): An unknown error has occurred.
-void char_delete2_accept_ack(int fd, int char_id, uint32 result)
+static void char_delete2_accept_ack(int fd, int char_id, uint32 result)
{// HC: <082a>.W <char id>.L <Msg:0-5>.L
-#if PACKETVER >= 20130000 /* not sure the exact date -- must refresh or client gets stuck */
+#if PACKETVER_MAIN_NUM >= 20130522 || PACKETVER_RE_NUM >= 20130327 || defined(PACKETVER_ZERO)
if( result == 1 ) {
struct char_session_data* sd = (struct char_session_data*)sockt->session[fd]->session_data;
- chr->mmo_char_send099d(fd, sd);
+ chr->send_HC_ACK_CHARINFO_PER_PAGE(fd, sd);
}
#endif
chr->delete2_accept_actual_ack(fd, char_id, result);
@@ -4155,7 +4226,7 @@ void char_delete2_accept_ack(int fd, int char_id, uint32 result)
/// 1 (0x718): none/success, (if char id not in deletion process): An unknown error has occurred.
/// 2 (0x719): A database error occurred.
/// Any (0x718): An unknown error has occurred.
-void char_delete2_cancel_ack(int fd, int char_id, uint32 result)
+static void char_delete2_cancel_ack(int fd, int char_id, uint32 result)
{// HC: <082c>.W <char id>.L <Msg:1-2>.L
WFIFOHEAD(fd,10);
WFIFOW(fd,0) = 0x82c;
@@ -4164,7 +4235,7 @@ void char_delete2_cancel_ack(int fd, int char_id, uint32 result)
WFIFOSET(fd,10);
}
-static void char_delete2_req(int fd, struct char_session_data* sd)
+static void char_delete2_req(int fd, struct char_session_data *sd)
{// CH: <0827>.W <char id>.L
int char_id, i;
char* data;
@@ -4235,7 +4306,7 @@ static void char_delete2_req(int fd, struct char_session_data* sd)
chr->delete2_ack(fd, char_id, 1, delete_date); // 1: success
}
-static void char_delete2_accept(int fd, struct char_session_data* sd)
+static void char_delete2_accept(int fd, struct char_session_data *sd)
{// CH: <0829>.W <char id>.L <birth date:YYMMDD>.6B
char birthdate[8+1];
int char_id, i;
@@ -4307,7 +4378,7 @@ static void char_delete2_accept(int fd, struct char_session_data* sd)
chr->delete2_accept_ack(fd, char_id, 1); // 1: success
}
-static void char_delete2_cancel(int fd, struct char_session_data* sd)
+static void char_delete2_cancel(int fd, struct char_session_data *sd)
{// CH: <082b>.W <char id>.L
int char_id, i;
@@ -4334,14 +4405,14 @@ static void char_delete2_cancel(int fd, struct char_session_data* sd)
chr->delete2_cancel_ack(fd, char_id, 1); // 1: success
}
-void char_send_account_id(int fd, int account_id)
+static void char_send_account_id(int fd, int account_id)
{
- WFIFOHEAD(fd,4);
- WFIFOL(fd,0) = account_id;
- WFIFOSET(fd,4);
+ WFIFOHEAD(fd, 4);
+ WFIFOL(fd, 0) = account_id;
+ WFIFOSET2(fd, 4);
}
-void char_parse_char_connect(int fd, struct char_session_data* sd, uint32 ipl)
+static void char_parse_char_connect(int fd, struct char_session_data *sd, uint32 ipl)
{
int account_id = RFIFOL(fd,2);
uint32 login_id1 = RFIFOL(fd,6);
@@ -4373,6 +4444,7 @@ void char_parse_char_connect(int fd, struct char_session_data* sd, uint32 ipl)
if( core->runflag != CHARSERVER_ST_RUNNING ) {
chr->auth_error(fd, 0);
+ sockt->eof(fd);
return;
}
@@ -4387,11 +4459,13 @@ void char_parse_char_connect(int fd, struct char_session_data* sd, uint32 ipl)
/* restrictions apply */
if( chr->server_type == CST_MAINTENANCE && node->group_id < char_maintenance_min_group_id ) {
chr->auth_error(fd, 0);
+ sockt->eof(fd);
return;
}
/* the client will already deny this request, this check is to avoid someone bypassing. */
if( chr->server_type == CST_PAYING && (time_t)node->expiration_time < time(NULL) ) {
chr->auth_error(fd, 0);
+ sockt->eof(fd);
return;
}
idb_remove(auth_db, account_id);
@@ -4403,23 +4477,38 @@ void char_parse_char_connect(int fd, struct char_session_data* sd, uint32 ipl)
loginif->auth(fd, sd, ipl);
} else { // if no login-server, we must refuse connection
chr->auth_error(fd, 0);
+ sockt->eof(fd);
}
}
}
-void char_send_map_info(int fd, int i, uint32 subnet_map_ip, struct mmo_charstatus *cd)
+static void char_send_map_info(int fd, int i, uint32 subnet_map_ip, struct mmo_charstatus *cd, char *dnsHost)
{
+#if PACKETVER < 20170329
+ const int cmd = 0x71;
+ const int len = 28;
+#else
+ const int cmd = 0xac5;
+ const int len = 156;
+#endif
nullpo_retv(cd);
- WFIFOHEAD(fd,28);
- WFIFOW(fd,0) = 0x71;
- WFIFOL(fd,2) = cd->char_id;
- mapindex->getmapname_ext(mapindex_id2name(cd->last_point.map), WFIFOP(fd,6));
- WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : chr->server[i].ip);
- WFIFOW(fd,26) = sockt->ntows(htons(chr->server[i].port)); // [!] LE byte order here [!]
- WFIFOSET(fd,28);
+ WFIFOHEAD(fd, len);
+ WFIFOW(fd, 0) = cmd;
+ WFIFOL(fd, 2) = cd->char_id;
+ mapindex->getmapname_ext(mapindex_id2name(cd->last_point.map), WFIFOP(fd, 6));
+ WFIFOL(fd, 22) = htonl((subnet_map_ip) ? subnet_map_ip : chr->server[i].ip);
+ WFIFOW(fd, 26) = sockt->ntows(htons(chr->server[i].port)); // [!] LE byte order here [!]
+#if PACKETVER >= 20170329
+ if (dnsHost != NULL) {
+ safestrncpy(WFIFOP(fd, 28), dnsHost, 128);
+ } else {
+ memset(WFIFOP(fd, 28), 0, 128);
+ }
+#endif
+ WFIFOSET(fd, len);
}
-void char_send_wait_char_server(int fd)
+static void char_send_wait_char_server(int fd)
{
WFIFOHEAD(fd, 24);
WFIFOW(fd, 0) = 0x840;
@@ -4428,7 +4517,7 @@ void char_send_wait_char_server(int fd)
WFIFOSET(fd, 24);
}
-int char_search_default_maps_mapserver(struct mmo_charstatus *cd)
+static int char_search_default_maps_mapserver(struct mmo_charstatus *cd)
{
int i;
int j;
@@ -4460,8 +4549,8 @@ int char_search_default_maps_mapserver(struct mmo_charstatus *cd)
return i;
}
-void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl) __attribute__((nonnull (2)));
-void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl)
+static void char_parse_char_select(int fd, struct char_session_data *sd, uint32 ipl) __attribute__((nonnull (2)));
+static void char_parse_char_select(int fd, struct char_session_data *sd, uint32 ipl)
{
struct mmo_charstatus char_dat;
struct mmo_charstatus *cd;
@@ -4535,8 +4624,19 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl)
// FIXME: Why are we re-escaping the name if it was already escaped in rename/make_new_char? [Panikon]
SQL->EscapeStringLen(inter->sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH));
if (SQL_ERROR == SQL->Query(inter->sql_handle,
- "INSERT INTO `%s`(`time`, `account_id`, `char_id`, `char_num`, `name`) VALUES (NOW(), '%d', '%d', '%d', '%s')",
- charlog_db, sd->account_id, cd->char_id, slot, esc_name))
+ "INSERT INTO `%s`("
+ " `time`, `char_msg`, `account_id`, `char_id`, `char_num`, `class`, `name`,"
+ " `str`, `agi`, `vit`, `int`, `dex`, `luk`,"
+ " `hair`, `hair_color`"
+ ") VALUES ("
+ " NOW(), 'char select', '%d', '%d', '%d', '%d', '%s',"
+ " '%d', '%d', '%d', '%d', '%d', '%d',"
+ " '%d', '%d')",
+ charlog_db,
+ sd->account_id, cd->char_id, slot, char_dat.class, esc_name,
+ char_dat.str, char_dat.agi, char_dat.vit, char_dat.int_, char_dat.dex, char_dat.luk,
+ char_dat.hair, char_dat.hair_color
+ ))
Sql_ShowDebug(inter->sql_handle);
}
ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
@@ -4576,7 +4676,7 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl)
subnet_map_ip = chr->lan_subnet_check(ipl);
//Send player to map
- chr->send_map_info(fd, i, subnet_map_ip, cd);
+ chr->send_map_info(fd, i, subnet_map_ip, cd, NULL);
// create temporary auth entry
CREATE(node, struct char_auth_node, 1);
@@ -4591,14 +4691,15 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl)
idb_put(auth_db, sd->account_id, node);
}
-void char_creation_failed(int fd, int result)
+static void char_creation_failed(int fd, int result)
{
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x6e;
/* Others I found [Ind] */
/* 0x02 = Symbols in Character Names are forbidden */
/* 0x03 = You are not eligible to open the Character Slot. */
- /* 0x0B = This service is only available for premium users. */
+ /* 0x0B = This service is only available for premium users. */
+ /* 0x0C = Character name is invalid. */
switch (result) {
case -1: WFIFOB(fd,2) = 0x00; break; // 'Charname already exists'
case -2: WFIFOB(fd,2) = 0xFF; break; // 'Char creation denied'
@@ -4614,7 +4715,7 @@ void char_creation_failed(int fd, int result)
WFIFOSET(fd,3);
}
-void char_creation_ok(int fd, struct mmo_charstatus *char_dat)
+static void char_creation_ok(int fd, struct mmo_charstatus *char_dat)
{
int len;
@@ -4625,21 +4726,35 @@ void char_creation_ok(int fd, struct mmo_charstatus *char_dat)
WFIFOSET(fd,len);
}
-void char_parse_char_create_new_char(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_create_new_char(int fd, struct char_session_data* sd)
+static void char_parse_char_create_new_char(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_create_new_char(int fd, struct char_session_data *sd)
{
int result;
if (!enable_char_creation) {
//turn character creation on/off [Kevin]
result = -2;
} else {
- #if PACKETVER >= 20151001
- result = chr->make_new_char_sql(sd, RFIFOP(fd,2), 1, 1, 1, 1, 1, 1, RFIFOB(fd,26), RFIFOW(fd,27), RFIFOW(fd,29), RFIFOW(fd, 31));
- #elif PACKETVER >= 20120307
- result = chr->make_new_char_sql(sd, RFIFOP(fd,2), 1, 1, 1, 1, 1, 1, RFIFOB(fd,26), RFIFOW(fd,27), RFIFOW(fd,29), JOB_NOVICE);
- #else
- result = chr->make_new_char_sql(sd, RFIFOP(fd,2), RFIFOB(fd,26), RFIFOB(fd,27), RFIFOB(fd,28), RFIFOB(fd,29), RFIFOB(fd,30), RFIFOB(fd,31), RFIFOB(fd,32), RFIFOW(fd,33), RFIFOW(fd,35), JOB_NOVICE);
- #endif
+#if PACKETVER >= 20151001
+ uint8 sex = RFIFOB(fd, 35);
+
+ switch (sex) {
+ case SEX_FEMALE:
+ sex = 'F';
+ break;
+ case SEX_MALE:
+ sex = 'M';
+ break;
+ default:
+ chr->creation_failed(fd, -2); // Char Creation Denied
+ RFIFOSKIP(fd, 36);
+ return;
+ }
+ result = chr->make_new_char_sql(sd, RFIFOP(fd, 2), 1, 1, 1, 1, 1, 1, RFIFOB(fd, 26), RFIFOW(fd, 27), RFIFOW(fd, 29), RFIFOL(fd, 31), sex);
+#elif PACKETVER >= 20120307
+ result = chr->make_new_char_sql(sd, RFIFOP(fd, 2), 1, 1, 1, 1, 1, 1, RFIFOB(fd, 26), RFIFOW(fd, 27), RFIFOW(fd, 29), JOB_NOVICE, 'U');
+#else
+ result = chr->make_new_char_sql(sd, RFIFOP(fd, 2), RFIFOB(fd, 26), RFIFOB(fd, 27), RFIFOB(fd, 28), RFIFOB(fd, 29), RFIFOB(fd, 30), RFIFOB(fd, 31), RFIFOB(fd, 32), RFIFOW(fd, 33), RFIFOW(fd, 35), JOB_NOVICE, 'U');
+#endif
}
//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
@@ -4665,7 +4780,7 @@ void char_parse_char_create_new_char(int fd, struct char_session_data* sd)
// flag:
// 0 = Incorrect Email address
-void char_delete_char_failed(int fd, int flag)
+static void char_delete_char_failed(int fd, int flag)
{
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x70;
@@ -4673,15 +4788,15 @@ void char_delete_char_failed(int fd, int flag)
WFIFOSET(fd,3);
}
-void char_delete_char_ok(int fd)
+static void char_delete_char_ok(int fd)
{
WFIFOHEAD(fd,2);
WFIFOW(fd,0) = 0x6f;
WFIFOSET(fd,2);
}
-void char_parse_char_delete_char(int fd, struct char_session_data* sd, unsigned short cmd) __attribute__((nonnull (2)));
-void char_parse_char_delete_char(int fd, struct char_session_data* sd, unsigned short cmd)
+static void char_parse_char_delete_char(int fd, struct char_session_data *sd, unsigned short cmd) __attribute__((nonnull (2)));
+static void char_parse_char_delete_char(int fd, struct char_session_data *sd, unsigned short cmd)
{
char email[40];
int cid = RFIFOL(fd,2);
@@ -4735,12 +4850,12 @@ void char_parse_char_delete_char(int fd, struct char_session_data* sd, unsigned
chr->delete_char_ok(fd);
}
-void char_parse_char_ping(int fd)
+static void char_parse_char_ping(int fd)
{
RFIFOSKIP(fd,6);
}
-void char_allow_rename(int fd, int flag)
+static void char_allow_rename(int fd, int flag)
{
WFIFOHEAD(fd, 4);
WFIFOW(fd,0) = 0x28e;
@@ -4748,12 +4863,11 @@ void char_allow_rename(int fd, int flag)
WFIFOSET(fd,4);
}
-void char_parse_char_rename_char(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_rename_char(int fd, struct char_session_data* sd)
+static void char_parse_char_rename_char(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_rename_char(int fd, struct char_session_data *sd)
{
int i, cid =RFIFOL(fd,2);
char name[NAME_LENGTH];
- char esc_name[NAME_LENGTH*2+1];
safestrncpy(name, RFIFOP(fd,6), NAME_LENGTH);
RFIFOSKIP(fd,30);
@@ -4762,8 +4876,7 @@ void char_parse_char_rename_char(int fd, struct char_session_data* sd)
return;
normalize_name(name,TRIM_CHARS);
- SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
- if( !chr->check_char_name(name,esc_name) ) {
+ if (chr->check_char_name(name, NULL) == 0) {
i = 1;
safestrncpy(sd->new_name, name, NAME_LENGTH);
} else {
@@ -4773,12 +4886,11 @@ void char_parse_char_rename_char(int fd, struct char_session_data* sd)
chr->allow_rename(fd, i);
}
-void char_parse_char_rename_char2(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_rename_char2(int fd, struct char_session_data* sd)
+static void char_parse_char_rename_char2(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_rename_char2(int fd, struct char_session_data *sd)
{
int i, aid = RFIFOL(fd,2), cid =RFIFOL(fd,6);
char name[NAME_LENGTH];
- char esc_name[NAME_LENGTH*2+1];
safestrncpy(name, RFIFOP(fd,10), NAME_LENGTH);
RFIFOSKIP(fd,34);
@@ -4789,19 +4901,17 @@ void char_parse_char_rename_char2(int fd, struct char_session_data* sd)
return;
normalize_name(name,TRIM_CHARS);
- SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
- if( !chr->check_char_name(name,esc_name) )
- {
+ if (chr->check_char_name(name, NULL) == 0) {
i = 1;
safestrncpy(sd->new_name, name, NAME_LENGTH);
- }
- else
+ } else {
i = 0;
+ }
chr->allow_rename(fd, i);
}
-void char_rename_char_ack(int fd, int flag)
+static void char_rename_char_ack(int fd, int flag)
{
WFIFOHEAD(fd, 4);
WFIFOW(fd,0) = 0x290;
@@ -4809,8 +4919,8 @@ void char_rename_char_ack(int fd, int flag)
WFIFOSET(fd,4);
}
-void char_parse_char_rename_char_confirm(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_rename_char_confirm(int fd, struct char_session_data* sd)
+static void char_parse_char_rename_char_confirm(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_rename_char_confirm(int fd, struct char_session_data *sd)
{
int i;
int cid = RFIFOL(fd,2);
@@ -4824,7 +4934,7 @@ void char_parse_char_rename_char_confirm(int fd, struct char_session_data* sd)
chr->rename_char_ack(fd, i);
}
-void char_captcha_notsupported(int fd)
+static void char_captcha_notsupported(int fd)
{
WFIFOHEAD(fd,5);
WFIFOW(fd,0) = 0x7e9;
@@ -4833,31 +4943,31 @@ void char_captcha_notsupported(int fd)
WFIFOSET(fd,5);
}
-void char_parse_char_request_captcha(int fd)
+static void char_parse_char_request_captcha(int fd)
{
chr->captcha_notsupported(fd);
RFIFOSKIP(fd,8);
}
-void char_parse_char_check_captcha(int fd)
+static void char_parse_char_check_captcha(int fd)
{
chr->captcha_notsupported(fd);
RFIFOSKIP(fd,32);
}
-void char_parse_char_delete2_req(int fd, struct char_session_data* sd)
+static void char_parse_char_delete2_req(int fd, struct char_session_data *sd)
{
chr->delete2_req(fd, sd);
RFIFOSKIP(fd,6);
}
-void char_parse_char_delete2_accept(int fd, struct char_session_data* sd)
+static void char_parse_char_delete2_accept(int fd, struct char_session_data *sd)
{
chr->delete2_accept(fd, sd);
RFIFOSKIP(fd,12);
}
-void char_parse_char_delete2_cancel(int fd, struct char_session_data* sd)
+static void char_parse_char_delete2_cancel(int fd, struct char_session_data *sd)
{
chr->delete2_cancel(fd, sd);
RFIFOSKIP(fd,6);
@@ -4866,15 +4976,15 @@ void char_parse_char_delete2_cancel(int fd, struct char_session_data* sd)
// flag:
// 0 - ok
// 3 - error
-void char_login_map_server_ack(int fd, uint8 flag)
+static void char_login_map_server_ack(int fd, uint8 flag)
{
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x2af9;
- WFIFOB(fd,2) = flag;
- WFIFOSET(fd,3);
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x2af9;
+ WFIFOB(fd, 2) = flag;
+ WFIFOSET2(fd, 3);
}
-void char_parse_char_login_map_server(int fd, uint32 ipl)
+static void char_parse_char_login_map_server(int fd, uint32 ipl)
{
char l_user[24], l_pass[24];
int i;
@@ -4889,6 +4999,7 @@ void char_parse_char_login_map_server(int fd, uint32 ipl)
!sockt->allowed_ip_check(ipl))
{
chr->login_map_server_ack(fd, 3); // Failure
+ sockt->eof(fd);
} else {
chr->login_map_server_ack(fd, 0); // Success
@@ -4898,6 +5009,7 @@ void char_parse_char_login_map_server(int fd, uint32 ipl)
chr->server[i].users = 0;
sockt->session[fd]->func_parse = chr->parse_frommap;
sockt->session[fd]->flag.server = 1;
+ sockt->session[fd]->flag.validate = 0;
sockt->realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
chr->mapif_init(fd);
}
@@ -4906,8 +5018,8 @@ void char_parse_char_login_map_server(int fd, uint32 ipl)
RFIFOSKIP(fd,60);
}
-void char_parse_char_pincode_check(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_pincode_check(int fd, struct char_session_data* sd)
+static void char_parse_char_pincode_check(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_pincode_check(int fd, struct char_session_data *sd)
{
if (RFIFOL(fd,2) == sd->account_id)
pincode->check(fd, sd);
@@ -4915,17 +5027,17 @@ void char_parse_char_pincode_check(int fd, struct char_session_data* sd)
RFIFOSKIP(fd, 10);
}
-void char_parse_char_pincode_window(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_pincode_window(int fd, struct char_session_data* sd)
+static void char_parse_char_pincode_window(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_pincode_window(int fd, struct char_session_data *sd)
{
if (RFIFOL(fd,2) == sd->account_id)
- pincode->sendstate(fd, sd, PINCODE_NOTSET);
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_NOTSET);
RFIFOSKIP(fd, 6);
}
-void char_parse_char_pincode_change(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_pincode_change(int fd, struct char_session_data* sd)
+static void char_parse_char_pincode_change(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_pincode_change(int fd, struct char_session_data *sd)
{
if (RFIFOL(fd,2) == sd->account_id)
pincode->change(fd, sd);
@@ -4933,21 +5045,21 @@ void char_parse_char_pincode_change(int fd, struct char_session_data* sd)
RFIFOSKIP(fd, 14);
}
-void char_parse_char_pincode_first_pin(int fd, struct char_session_data* sd) __attribute__((nonnull (2)));
-void char_parse_char_pincode_first_pin(int fd, struct char_session_data* sd)
+static void char_parse_char_pincode_first_pin(int fd, struct char_session_data *sd) __attribute__((nonnull (2)));
+static void char_parse_char_pincode_first_pin(int fd, struct char_session_data *sd)
{
if (RFIFOL(fd,2) == sd->account_id)
pincode->setnew (fd, sd);
RFIFOSKIP(fd, 10);
}
-void char_parse_char_request_chars(int fd, struct char_session_data* sd)
+static void char_parse_char_request_chars(int fd, struct char_session_data *sd)
{
- chr->mmo_char_send099d(fd, sd);
+ chr->send_HC_ACK_CHARINFO_PER_PAGE(fd, sd);
RFIFOSKIP(fd,2);
}
-void char_change_character_slot_ack(int fd, bool ret)
+static void char_change_character_slot_ack(int fd, bool ret)
{
WFIFOHEAD(fd, 8);
WFIFOW(fd, 0) = 0x8d5;
@@ -4957,28 +5069,28 @@ void char_change_character_slot_ack(int fd, bool ret)
WFIFOSET(fd, 8);
}
-void char_parse_char_move_character(int fd, struct char_session_data* sd)
+static void char_parse_char_move_character(int fd, struct char_session_data *sd)
{
bool ret = chr->char_slotchange(sd, fd, RFIFOW(fd, 2), RFIFOW(fd, 4));
chr->change_character_slot_ack(fd, ret);
/* for some stupid reason it requires the char data again (gravity -_-) */
if( ret )
-#if PACKETVER >= 20130000
- chr->mmo_char_send099d(fd, sd);
+#if PACKETVER_MAIN_NUM >= 20130522 || PACKETVER_RE_NUM >= 20130327 || defined(PACKETVER_ZERO)
+ chr->send_HC_ACK_CHARINFO_PER_PAGE(fd, sd);
#else
chr->mmo_char_send_characters(fd, sd);
#endif
RFIFOSKIP(fd, 8);
}
-int char_parse_char_unknown_packet(int fd, uint32 ipl)
+static int char_parse_char_unknown_packet(int fd, uint32 ipl)
{
ShowError("chr->parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), sockt->ip2str(ipl, NULL));
sockt->eof(fd);
return 1;
}
-int char_parse_char(int fd)
+static int char_parse_char(int fd)
{
unsigned short cmd;
struct char_session_data* sd;
@@ -5042,7 +5154,7 @@ int char_parse_char(int fd)
// S 0a39 <name>.24B <slot>.B <hair color>.W <hair style>.W <starting job class ID>.W <Unknown>.(W or 2 B's)??? <sex>.B
case 0xa39:
{
- FIFOSD_CHECK(36);
+ FIFOSD_CHECK(36);
#elif PACKETVER >= 20120307
// S 0970 <name>.24B <slot>.B <hair color>.W <hair style>.W
case 0x970:
@@ -5195,71 +5307,8 @@ int char_parse_char(int fd)
return 0;
}
-int mapif_sendall(const unsigned char *buf, unsigned int len)
-{
- int i, c;
-
- nullpo_ret(buf);
- c = 0;
- for(i = 0; i < ARRAYLENGTH(chr->server); i++) {
- int fd;
- if ((fd = chr->server[i].fd) > 0) {
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- c++;
- }
- }
-
- return c;
-}
-
-int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
-{
- int i, c;
-
- nullpo_ret(buf);
- c = 0;
- for(i = 0; i < ARRAYLENGTH(chr->server); i++) {
- int fd;
- if ((fd = chr->server[i].fd) > 0 && fd != sfd) {
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- c++;
- }
- }
-
- return c;
-}
-
-int mapif_send(int fd, unsigned char *buf, unsigned int len)
-{
- nullpo_ret(buf);
- if (fd >= 0) {
- int i;
- ARR_FIND( 0, ARRAYLENGTH(chr->server), i, fd == chr->server[i].fd );
- if( i < ARRAYLENGTH(chr->server) )
- {
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- return 1;
- }
- }
- return 0;
-}
-
-void mapif_send_users_count(int users)
+static int char_broadcast_user_count(int tid, int64 tick, int id, intptr_t data)
{
- uint8 buf[6];
- // send number of players to all map-servers
- WBUFW(buf,0) = 0x2b00;
- WBUFL(buf,2) = users;
- mapif->sendall(buf,6);
-}
-
-int char_broadcast_user_count(int tid, int64 tick, int id, intptr_t data) {
int users = chr->count_users();
// only send an update when needed
@@ -5298,7 +5347,8 @@ static int char_send_accounts_tologin_sub(union DBKey key, struct DBData *data,
return 0;
}
-int char_send_accounts_tologin(int tid, int64 tick, int id, intptr_t data) {
+static int char_send_accounts_tologin(int tid, int64 tick, int id, intptr_t data)
+{
if (chr->login_fd > 0 && sockt->session[chr->login_fd])
{
// send account list to login server
@@ -5315,7 +5365,8 @@ int char_send_accounts_tologin(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int char_check_connect_login_server(int tid, int64 tick, int id, intptr_t data) {
+static int char_check_connect_login_server(int tid, int64 tick, int id, intptr_t data)
+{
if (chr->login_fd > 0 && sockt->session[chr->login_fd] != NULL)
return 0;
@@ -5328,6 +5379,7 @@ int char_check_connect_login_server(int tid, int64 tick, int id, intptr_t data)
sockt->session[chr->login_fd]->func_parse = chr->parse_fromlogin;
sockt->session[chr->login_fd]->flag.server = 1;
+ sockt->session[chr->login_fd]->flag.validate = 0;
sockt->realloc_fifo(chr->login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
loginif->connect_to_server();
@@ -5339,7 +5391,8 @@ int char_check_connect_login_server(int tid, int64 tick, int id, intptr_t data)
//Invoked 15 seconds after mapif->disconnectplayer in case the map server doesn't
//replies/disconnect the player we tried to kick. [Skotlex]
//------------------------------------------------
-static int char_waiting_disconnect(int tid, int64 tick, int id, intptr_t data) {
+static int char_waiting_disconnect(int tid, int64 tick, int id, intptr_t data)
+{
struct online_char_data* character;
if ((character = (struct online_char_data*)idb_get(chr->online_char_db, id)) != NULL && character->waiting_disconnect == tid) {
//Mark it offline due to timeout.
@@ -5366,7 +5419,8 @@ static int char_online_data_cleanup_sub(union DBKey key, struct DBData *data, va
return 0;
}
-static int char_online_data_cleanup(int tid, int64 tick, int id, intptr_t data) {
+static int char_online_data_cleanup(int tid, int64 tick, int id, intptr_t data)
+{
chr->online_char_db->foreach(chr->online_char_db, chr->online_data_cleanup_sub);
return 0;
}
@@ -5379,7 +5433,7 @@ static int char_online_data_cleanup(int tid, int64 tick, int id, intptr_t data)
*
* @retval false in case of error.
*/
-bool char_sql_config_read(const char *filename, bool imported)
+static bool char_sql_config_read(const char *filename, bool imported)
{
struct config_t config;
const struct config_setting_t *setting = NULL;
@@ -5436,7 +5490,7 @@ bool char_sql_config_read(const char *filename, bool imported)
*
* @retval false in case of error.
*/
-bool char_sql_config_read_registry(const char *filename, const struct config_t *config, bool imported)
+static bool char_sql_config_read_registry(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5467,7 +5521,7 @@ bool char_sql_config_read_registry(const char *filename, const struct config_t *
*
* @retval false in case of error.
*/
-bool char_sql_config_read_pc(const char *filename, const struct config_t *config, bool imported)
+static bool char_sql_config_read_pc(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5483,6 +5537,7 @@ bool char_sql_config_read_pc(const char *filename, const struct config_t *config
libconfig->setting_lookup_mutable_string(setting, "hotkey_db", hotkey_db, sizeof(hotkey_db));
libconfig->setting_lookup_mutable_string(setting, "scdata_db", scdata_db, sizeof(scdata_db));
libconfig->setting_lookup_mutable_string(setting, "inventory_db", inventory_db, sizeof(inventory_db));
+ libconfig->setting_lookup_mutable_string(setting, "achievement_db", char_achievement_db, sizeof(char_achievement_db));
libconfig->setting_lookup_mutable_string(setting, "cart_db", cart_db, sizeof(cart_db));
libconfig->setting_lookup_mutable_string(setting, "charlog_db", charlog_db, sizeof(charlog_db));
libconfig->setting_lookup_mutable_string(setting, "storage_db", storage_db, sizeof(storage_db));
@@ -5513,7 +5568,7 @@ bool char_sql_config_read_pc(const char *filename, const struct config_t *config
*
* @retval false in case of error.
*/
-bool char_sql_config_read_guild(const char *filename, const struct config_t *config, bool imported)
+static bool char_sql_config_read_guild(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5547,7 +5602,7 @@ bool char_sql_config_read_guild(const char *filename, const struct config_t *con
*
* @retval false in case of error.
*/
-bool char_config_read(const char *filename, bool imported)
+static bool char_config_read(const char *filename, bool imported)
{
struct config_t config;
const char *import = NULL;
@@ -5603,7 +5658,7 @@ bool char_config_read(const char *filename, bool imported)
*
* @retval false in case of error.
*/
-bool char_config_read_top(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_top(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5647,7 +5702,7 @@ bool char_config_read_top(const char *filename, const struct config_t *config, b
*
* @retval false in case of error.
*/
-bool char_config_read_inter(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_inter(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
const char *str = NULL;
@@ -5691,7 +5746,7 @@ bool char_config_read_inter(const char *filename, const struct config_t *config,
*
* @retval false in case of error.
*/
-bool char_config_read_database(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_database(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5723,7 +5778,7 @@ bool char_config_read_database(const char *filename, const struct config_t *conf
*
* @retval false in case of error.
*/
-bool char_config_read_console(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_console(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting;
@@ -5756,7 +5811,7 @@ bool char_config_read_console(const char *filename, const struct config_t *confi
*
* @retval false in case of error.
*/
-bool char_config_read_player(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_player(const char *filename, const struct config_t *config, bool imported)
{
bool retval = true;
@@ -5784,7 +5839,7 @@ bool char_config_read_player(const char *filename, const struct config_t *config
*
* @retval false in case of error.
*/
-bool char_config_read_player_fame(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_player_fame(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5828,7 +5883,7 @@ bool char_config_read_player_fame(const char *filename, const struct config_t *c
*
* @retval false in case of error.
*/
-bool char_config_read_player_deletion(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_player_deletion(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5857,7 +5912,7 @@ bool char_config_read_player_deletion(const char *filename, const struct config_
*
* @retval false in case of error.
*/
-bool char_config_read_player_name(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_player_name(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -5874,6 +5929,7 @@ bool char_config_read_player_name(const char *filename, const struct config_t *c
libconfig->setting_lookup_mutable_string(setting, "name_letters", char_name_letters, sizeof(char_name_letters));
libconfig->setting_lookup_int(setting, "name_option", &char_name_option);
libconfig->setting_lookup_bool_real(setting, "name_ignoring_case", &name_ignoring_case);
+ libconfig->setting_lookup_bool_real(setting, "use_aegis_rename", &char_aegis_rename);
return true;
}
@@ -5883,7 +5939,7 @@ bool char_config_read_player_name(const char *filename, const struct config_t *c
*
* @param setting The already retrieved start_item setting.
*/
-void char_config_set_start_item(const struct config_setting_t *setting)
+static void char_config_set_start_item(const struct config_setting_t *setting)
{
int i, count;
@@ -5932,7 +5988,7 @@ void char_config_set_start_item(const struct config_setting_t *setting)
*
* @retval false in case of error.
*/
-bool char_config_read_player_new(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_player_new(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL, *setting2 = NULL;
#ifdef RENEWAL
@@ -5988,7 +6044,7 @@ bool char_config_read_player_new(const char *filename, const struct config_t *co
*
* @retval false in case of error.
*/
-bool char_config_read_permission(const char *filename, const struct config_t *config, bool imported)
+static bool char_config_read_permission(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -6032,7 +6088,7 @@ bool char_config_read_permission(const char *filename, const struct config_t *co
*
* @retval false in case of error.
*/
-bool char_config_set_ip(const char *type, const char *value, uint32 *out_ip, char *out_ip_str)
+static bool char_config_set_ip(const char *type, const char *value, uint32 *out_ip, char *out_ip_str)
{
uint32 ip = 0;
@@ -6050,7 +6106,8 @@ bool char_config_set_ip(const char *type, const char *value, uint32 *out_ip, cha
return true;
}
-int do_final(void) {
+int do_final(void)
+{
int i;
ShowStatus("Terminating...\n");
@@ -6066,6 +6123,7 @@ int do_final(void) {
do_final_mapif();
loginif->final();
+ pincode->final();
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s`", ragsrvinfo_db) )
Sql_ShowDebug(inter->sql_handle);
@@ -6108,12 +6166,13 @@ void do_abort(void)
{
}
-void set_server_type(void) {
+void set_server_type(void)
+{
SERVER_TYPE = SERVER_TYPE_CHAR;
}
/// Called when a terminate signal is received.
-void do_shutdown(void)
+static void do_shutdown(void)
{
if( core->runflag != CHARSERVER_ST_SHUTDOWN )
{
@@ -6189,7 +6248,8 @@ void cmdline_args_init_local(void)
CMDLINEARG_DEF2(net-config, netconfig, "Alternative network configuration.", CMDLINE_OPT_PARAM);
}
-int do_init(int argc, char **argv) {
+int do_init(int argc, char **argv)
+{
int i;
memset(&skillid2idx, 0, sizeof(skillid2idx));
@@ -6212,6 +6272,7 @@ int do_init(int argc, char **argv) {
//Read map indexes
mapindex->init();
+ pincode->init();
#ifdef RENEWAL
start_point.map = mapindex->name2id("iz_int");
@@ -6311,6 +6372,7 @@ int do_init(int argc, char **argv) {
Sql_ShowDebug(inter->sql_handle);
sockt->set_defaultparse(chr->parse_char);
+ sockt->validate = true;
if ((chr->char_fd = sockt->make_listen_bind(bind_ip,chr->port)) == -1) {
ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",chr->port);
@@ -6343,6 +6405,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();
@@ -6352,6 +6415,8 @@ void char_load_defaults(void)
inter_pet_defaults();
inter_quest_defaults();
inter_storage_defaults();
+ inter_rodex_defaults();
+ inter_achievement_defaults();
inter_defaults();
geoip_defaults();
}
@@ -6395,18 +6460,20 @@ void char_defaults(void)
chr->create_charstatus = char_create_charstatus;
chr->mmo_char_tosql = char_mmo_char_tosql;
chr->memitemdata_to_sql = char_memitemdata_to_sql;
+ chr->getitemdata_from_sql = char_getitemdata_from_sql;
chr->mmo_gender = char_mmo_gender;
chr->mmo_chars_fromsql = char_mmo_chars_fromsql;
chr->mmo_char_fromsql = char_mmo_char_fromsql;
chr->mmo_char_sql_init = char_mmo_char_sql_init;
chr->char_slotchange = char_char_slotchange;
chr->rename_char_sql = char_rename_char_sql;
+ chr->name_exists = char_name_exists;
chr->check_char_name = char_check_char_name;
chr->make_new_char_sql = char_make_new_char_sql;
chr->divorce_char_sql = char_divorce_char_sql;
chr->count_users = char_count_users;
chr->mmo_char_tobuf = char_mmo_char_tobuf;
- chr->mmo_char_send099d = char_mmo_char_send099d;
+ chr->send_HC_ACK_CHARINFO_PER_PAGE = char_send_HC_ACK_CHARINFO_PER_PAGE;
chr->mmo_char_send_ban_list = char_mmo_char_send_ban_list;
chr->mmo_char_send_slots_info = char_mmo_char_send_slots_info;
chr->mmo_char_send_characters = char_mmo_char_send_characters;
@@ -6479,7 +6546,6 @@ void char_defaults(void)
chr->map_auth_failed = char_map_auth_failed;
chr->parse_frommap_auth_request = char_parse_frommap_auth_request;
chr->parse_frommap_update_ip = char_parse_frommap_update_ip;
- chr->parse_frommap_request_stats_report = char_parse_frommap_request_stats_report;
chr->parse_frommap_scdata_update = char_parse_frommap_scdata_update;
chr->parse_frommap_scdata_delete = char_parse_frommap_scdata_delete;
chr->parse_frommap = char_parse_frommap;
diff --git a/src/char/char.h b/src/char/char.h
index d7bc96e13..914530537 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -139,19 +139,21 @@ struct char_interface {
void (*set_all_offline_sql) (void);
struct DBData (*create_charstatus) (union DBKey key, va_list args);
int (*mmo_char_tosql) (int char_id, struct mmo_charstatus* p);
- int (*memitemdata_to_sql) (const struct item items[], int max, int id, int tableswitch);
+ int (*getitemdata_from_sql) (struct item *items, int max, int guid, enum inventory_table_type table);
+ int (*memitemdata_to_sql) (const struct item items[], int id, enum inventory_table_type table);
int (*mmo_gender) (const struct char_session_data *sd, const struct mmo_charstatus *p, char sex);
- int (*mmo_chars_fromsql) (struct char_session_data* sd, uint8* buf);
+ int (*mmo_chars_fromsql) (struct char_session_data* sd, uint8* buf, int *count);
int (*mmo_char_fromsql) (int char_id, struct mmo_charstatus* p, bool load_everything);
int (*mmo_char_sql_init) (void);
bool (*char_slotchange) (struct char_session_data *sd, int fd, unsigned short from, unsigned short to);
int (*rename_char_sql) (struct char_session_data *sd, int char_id);
- int (*check_char_name) (char * name, char * esc_name);
- int (*make_new_char_sql) (struct char_session_data *sd, const char *name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, short starting_job);
+ bool (*name_exists) (const char *name, const char *esc_name);
+ int (*check_char_name) (const char *name, const char *esc_name);
+ int (*make_new_char_sql) (struct char_session_data *sd, const char *name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, short starting_job, uint8 sex);
int (*divorce_char_sql) (int partner_id1, int partner_id2);
int (*count_users) (void);
int (*mmo_char_tobuf) (uint8* buffer, struct mmo_charstatus* p);
- void (*mmo_char_send099d) (int fd, struct char_session_data *sd);
+ void (*send_HC_ACK_CHARINFO_PER_PAGE) (int fd, struct char_session_data *sd);
void (*mmo_char_send_ban_list) (int fd, struct char_session_data *sd);
void (*mmo_char_send_slots_info) (int fd, struct char_session_data* sd);
int (*mmo_char_send_characters) (int fd, struct char_session_data* sd);
@@ -224,7 +226,6 @@ struct char_interface {
void (*map_auth_failed) (int fd, int account_id, int char_id, int login_id1, char sex, uint32 ip);
void (*parse_frommap_auth_request) (int fd, int id);
void (*parse_frommap_update_ip) (int fd, int id);
- void (*parse_frommap_request_stats_report) (int fd);
void (*parse_frommap_scdata_update) (int fd);
void (*parse_frommap_scdata_delete) (int fd);
int (*parse_frommap) (int fd);
@@ -240,7 +241,7 @@ struct char_interface {
void (*delete2_cancel) (int fd, struct char_session_data* sd);
void (*send_account_id) (int fd, int account_id);
void (*parse_char_connect) (int fd, struct char_session_data* sd, uint32 ipl);
- void (*send_map_info) (int fd, int i, uint32 subnet_map_ip, struct mmo_charstatus *cd);
+ void (*send_map_info) (int fd, int i, uint32 subnet_map_ip, struct mmo_charstatus *cd, char *dnsHost);
void (*send_wait_char_server) (int fd);
int (*search_default_maps_mapserver) (struct mmo_charstatus *cd);
void (*parse_char_select) (int fd, struct char_session_data* sd, uint32 ipl);
@@ -327,6 +328,8 @@ extern char pet_db[256];
extern char mail_db[256];
extern char auction_db[256];
extern char quest_db[256];
+extern char rodex_db[256];
+extern char rodex_item_db[256];
extern char homunculus_db[256];
extern char skill_homunculus_db[256];
extern char mercenary_db[256];
@@ -337,6 +340,7 @@ extern char acc_reg_num_db[32];
extern char acc_reg_str_db[32];
extern char char_reg_str_db[32];
extern char char_reg_num_db[32];
+extern char char_achievement_db[256];
extern int guild_exp_rate;
diff --git a/src/char/geoip.c b/src/char/geoip.c
index 0b84d2b09..2870e5f0c 100644
--- a/src/char/geoip.c
+++ b/src/char/geoip.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -30,9 +30,9 @@
#include <stdio.h>
#include <sys/stat.h> // for stat/lstat/fstat - [Dekamaster/Ultimate GM Tool]
-struct s_geoip geoip_data;
+static struct s_geoip geoip_data;
-struct geoip_interface geoip_s;
+static struct geoip_interface geoip_s;
struct geoip_interface *geoip;
/* [Dekamaster/Nightroad] */
@@ -40,36 +40,38 @@ struct geoip_interface *geoip;
#define GEOIP_STRUCTURE_INFO_MAX_SIZE 20
#define GEOIP_COUNTRY_BEGIN 16776960
-const char * geoip_countryname[GEOIP_MAX_COUNTRIES] = {"Unknown","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
- "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
- "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
- "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
- "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
- "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
- "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
- "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
- "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
- "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
- "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
- "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
- "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
- "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
- "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
- "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
- "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
- "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
- "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
- "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
- "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
- "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
- "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
- "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
- "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
- "Saint Barthelemy", "Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"};
+static const char *geoip_countryname[GEOIP_MAX_COUNTRIES] = {
+ "Unknown","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
+ "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
+ "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
+ "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
+ "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
+ "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
+ "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
+ "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
+ "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
+ "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
+ "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
+ "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
+ "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
+ "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
+ "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
+ "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
+ "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
+ "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
+ "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
+ "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
+ "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
+ "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
+ "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
+ "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
+ "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
+ "Saint Barthelemy", "Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"
+};
/* [Dekamaster/Nightroad] */
/* WHY NOT A DBMAP: There are millions of entries in GeoIP and it has its own algorithm to go quickly through them, a DBMap wouldn't be efficient */
-const char* geoip_getcountry(uint32 ipnum)
+static const char *geoip_getcountry(uint32 ipnum)
{
int depth;
unsigned int x;
@@ -111,7 +113,7 @@ const char* geoip_getcountry(uint32 ipnum)
* Disables GeoIP
* frees geoip.cache
**/
-void geoip_final(bool shutdown)
+static void geoip_final(bool shutdown)
{
if (geoip->data->cache) {
aFree(geoip->data->cache);
@@ -130,7 +132,7 @@ void geoip_final(bool shutdown)
* geoip.cache should be freed after use!
* http://dev.maxmind.com/geoip/legacy/geolite/
**/
-void geoip_init(void)
+static void geoip_init(void)
{
int fno;
char db_type = 1;
diff --git a/src/char/geoip.h b/src/char/geoip.h
index c5d71f5e1..be9fe4fff 100644
--- a/src/char/geoip.h
+++ b/src/char/geoip.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
diff --git a/src/char/int_achievement.c b/src/char/int_achievement.c
new file mode 100644
index 000000000..14311ecf0
--- /dev/null
+++ b/src/char/int_achievement.c
@@ -0,0 +1,252 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2017 Hercules Dev Team
+* Copyright (C) Smokexyz
+*
+* 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 "int_achievement.h"
+
+#include "char/char.h"
+#include "char/inter.h"
+#include "char/mapif.h"
+
+#include "common/db.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 <stdio.h>
+#include <stdlib.h>
+
+static struct inter_achievement_interface inter_achievement_s;
+struct inter_achievement_interface *inter_achievement;
+
+/**
+ * Saves changed achievements for a character.
+ * @param[in] char_id character identifier.
+ * @param[out] cp pointer to loaded achievements.
+ * @param[in] p pointer to map-sent character achievements.
+ * @return number of achievements saved.
+ */
+static int inter_achievement_tosql(int char_id, struct char_achievements *cp, const struct char_achievements *p)
+{
+ StringBuf buf;
+ int i = 0, rows = 0;
+
+ nullpo_ret(cp);
+ nullpo_ret(p);
+ Assert_ret(char_id > 0);
+
+ StrBuf->Init(&buf);
+ StrBuf->Printf(&buf, "REPLACE INTO `%s` (`char_id`, `ach_id`, `completed_at`, `rewarded_at`", char_achievement_db);
+ for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
+ StrBuf->Printf(&buf, ", `obj_%d`", i);
+ StrBuf->AppendStr(&buf, ") VALUES ");
+
+ for (i = 0; i < VECTOR_LENGTH(*p); i++) {
+ int j = 0;
+ bool save = false;
+ struct achievement *pa = &VECTOR_INDEX(*p, i), *cpa = NULL;
+
+ ARR_FIND(0, VECTOR_LENGTH(*cp), j, ((cpa = &VECTOR_INDEX(*cp, j)) && cpa->id == pa->id));
+
+ if (j == VECTOR_LENGTH(*cp))
+ save = true;
+ else if (memcmp(cpa, pa, sizeof(struct achievement)) != 0)
+ save = true;
+
+ if (save) {
+ StrBuf->Printf(&buf, "%s('%d', '%d', '%"PRId64"', '%"PRId64"'", rows ?", ":"", char_id, pa->id, (int64)pa->completed_at, (int64)pa->rewarded_at);
+ for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++)
+ StrBuf->Printf(&buf, ", '%d'", pa->objective[j]);
+ StrBuf->AppendStr(&buf, ")");
+ rows++;
+ }
+ }
+
+ if (rows > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
+ Sql_ShowDebug(inter->sql_handle);
+ StrBuf->Destroy(&buf); // Destroy the buffer.
+ return 0;
+ }
+ // Destroy the buffer.
+ StrBuf->Destroy(&buf);
+
+ if (rows) {
+ ShowInfo("achievements saved for char %d (total: %d, saved: %d)\n", char_id, VECTOR_LENGTH(*p), rows);
+
+ /* Sync with inter-db acheivements. */
+ VECTOR_CLEAR(*cp);
+ VECTOR_ENSURE(*cp, VECTOR_LENGTH(*p), 1);
+ VECTOR_PUSHARRAY(*cp, VECTOR_DATA(*p), VECTOR_LENGTH(*p));
+ }
+
+ return rows;
+}
+
+/**
+ * Retrieves all achievements of a character.
+ * @param[in] char_id character identifier.
+ * @param[out] cp pointer to character achievements structure.
+ * @return true on success, false on failure.
+ */
+static bool inter_achievement_fromsql(int char_id, struct char_achievements *cp)
+{
+ StringBuf buf;
+ char *data;
+ int i = 0, num_rows = 0;
+
+ nullpo_ret(cp);
+
+ Assert_ret(char_id > 0);
+
+ // char_achievements (`char_id`, `ach_id`, `completed_at`, `rewarded_at`, `obj_0`, `obj_2`, ...`obj_9`)
+ StrBuf->Init(&buf);
+ StrBuf->AppendStr(&buf, "SELECT `ach_id`, `completed_at`, `rewarded_at`");
+ for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
+ StrBuf->Printf(&buf, ", `obj_%d`", i);
+ StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id` = '%d' ORDER BY `ach_id`", char_achievement_db, char_id);
+
+ if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
+ Sql_ShowDebug(inter->sql_handle);
+ StrBuf->Destroy(&buf);
+ return false;
+ }
+
+ VECTOR_CLEAR(*cp);
+
+ if ((num_rows = (int) SQL->NumRows(inter->sql_handle)) != 0) {
+ int j = 0;
+
+ VECTOR_ENSURE(*cp, num_rows, 1);
+
+ for (i = 0; i < num_rows && SQL_SUCCESS == SQL->NextRow(inter->sql_handle); i++) {
+ struct achievement t_ach = { 0 };
+ SQL->GetData(inter->sql_handle, 0, &data, NULL); t_ach.id = atoi(data);
+ SQL->GetData(inter->sql_handle, 1, &data, NULL); t_ach.completed_at = atoi(data);
+ SQL->GetData(inter->sql_handle, 2, &data, NULL); t_ach.rewarded_at = atoi(data);
+ /* Objectives */
+ for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++) {
+ SQL->GetData(inter->sql_handle, j + 3, &data, NULL);
+ t_ach.objective[j] = atoi(data);
+ }
+ /* Add Entry */
+ VECTOR_PUSH(*cp, t_ach);
+ }
+ }
+
+ SQL->FreeResult(inter->sql_handle);
+
+ StrBuf->Destroy(&buf);
+
+ if (num_rows > 0)
+ ShowInfo("achievements loaded for char %d (total: %d)\n", char_id, num_rows);
+
+ return true;
+}
+
+/**
+ * Handles checking of map server packets and calls appropriate functions.
+ * @param fd socket descriptor.
+ * @return 0 on failure, 1 on succes.
+ */
+static int inter_achievement_parse_frommap(int fd)
+{
+ RFIFOHEAD(fd);
+
+ switch (RFIFOW(fd,0)) {
+ case 0x3012:
+ mapif->pLoadAchievements(fd);
+ break;
+ case 0x3013:
+ mapif->pSaveAchievements(fd);
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * Initialization function
+ */
+static int inter_achievement_sql_init(void)
+{
+ // Initialize the loaded db storage.
+ // used as a comparand against map-server achievement data before saving.
+ inter_achievement->char_achievements = idb_alloc(DB_OPT_RELEASE_DATA);
+ return 1;
+}
+
+/**
+ * This function ensures idb's entry.
+ */
+static struct DBData inter_achievement_ensure_char_achievements(union DBKey key, va_list args)
+{
+ struct char_achievements *ca = NULL;
+
+ CREATE(ca, struct char_achievements, 1);
+ VECTOR_INIT(*ca);
+
+ return DB->ptr2data(ca);
+}
+
+/**
+ * Cleaning function called through db_destroy()
+ */
+static int inter_achievement_char_achievements_clear(union DBKey key, struct DBData *data, va_list args)
+{
+ struct char_achievements *ca = DB->data2ptr(data);
+
+ VECTOR_CLEAR(*ca);
+
+ return 0;
+}
+
+/**
+ * Finalization function.
+ */
+static void inter_achievement_sql_final(void)
+{
+ inter_achievement->char_achievements->destroy(inter_achievement->char_achievements, inter_achievement->char_achievements_clear);
+}
+
+/**
+ * Inter-achievement interface.
+ */
+void inter_achievement_defaults(void)
+{
+ inter_achievement = &inter_achievement_s;
+ /* */
+ inter_achievement->ensure_char_achievements = inter_achievement_ensure_char_achievements;
+ /* */
+ inter_achievement->sql_init = inter_achievement_sql_init;
+ inter_achievement->sql_final = inter_achievement_sql_final;
+ /* */
+ inter_achievement->tosql = inter_achievement_tosql;
+ inter_achievement->fromsql = inter_achievement_fromsql;
+ /* */
+ inter_achievement->parse_frommap = inter_achievement_parse_frommap;
+ inter_achievement->char_achievements_clear = inter_achievement_char_achievements_clear;
+}
diff --git a/src/char/int_achievement.h b/src/char/int_achievement.h
new file mode 100644
index 000000000..4a44a798d
--- /dev/null
+++ b/src/char/int_achievement.h
@@ -0,0 +1,53 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2017 Hercules Dev Team
+* Copyright (C) Smokexyz
+*
+* 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_ACHIEVEMENT_H
+#define CHAR_INT_ACHIEVEMENT_H
+
+#include "common/hercules.h"
+#include "common/db.h"
+
+struct achievement;
+struct char_achievements;
+
+/**
+ * inter_achievement Interface
+ */
+struct inter_achievement_interface {
+ struct DBMap *char_achievements;
+ /* */
+ int (*sql_init) (void);
+ void (*sql_final) (void);
+ /* */
+ int (*tosql) (int char_id, struct char_achievements *cp, const struct char_achievements *p);
+ bool (*fromsql) (int char_id, struct char_achievements *a);
+ /* */
+ struct DBData(*ensure_char_achievements) (union DBKey key, va_list args);
+ int (*char_achievements_clear) (union DBKey key, struct DBData *data, va_list args);
+ /* */
+ int (*parse_frommap) (int fd);
+};
+
+#ifdef HERCULES_CORE
+void inter_achievement_defaults(void);
+#endif // HERCULES_CORE
+
+HPShared struct inter_achievement_interface *inter_achievement;
+#endif /* CHAR_INT_ACHIEVEMENT_H */
diff --git a/src/char/int_auction.c b/src/char/int_auction.c
index bf690327c..1e5b0a06d 100644
--- a/src/char/int_auction.c
+++ b/src/char/int_auction.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -40,7 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_auction_interface inter_auction_s;
+static struct inter_auction_interface inter_auction_s;
struct inter_auction_interface *inter_auction;
static int inter_auction_count(int char_id, bool buy)
@@ -59,7 +59,7 @@ static int inter_auction_count(int char_id, bool buy)
return i;
}
-void inter_auction_save(struct auction_data *auction)
+static void inter_auction_save(struct auction_data *auction)
{
int j;
StringBuf buf;
@@ -71,8 +71,10 @@ void inter_auction_save(struct auction_data *auction)
StrBuf->Init(&buf);
StrBuf->Printf(&buf, "UPDATE `%s` SET `seller_id` = '%d', `seller_name` = ?, `buyer_id` = '%d', `buyer_name` = ?, `price` = '%d', `buynow` = '%d', `hours` = '%d', `timestamp` = '%lu', `nameid` = '%d', `item_name` = ?, `type` = '%d', `refine` = '%d', `attribute` = '%d'",
auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute);
- for( j = 0; j < MAX_SLOTS; j++ )
+ for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ", `card%d` = '%d'", j, auction->item.card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ", `opt_idx%d` = '%d', `opt_val%d` = '%d'", j, auction->item.option[j].index, j, auction->item.option[j].value);
StrBuf->Printf(&buf, " WHERE `auction_id` = '%u'", auction->auction_id);
stmt = SQL->StmtMalloc(inter->sql_handle);
@@ -89,39 +91,41 @@ void inter_auction_save(struct auction_data *auction)
StrBuf->Destroy(&buf);
}
-unsigned int inter_auction_create(struct auction_data *auction)
+static unsigned int inter_auction_create(struct auction_data *auction)
{
int j;
StringBuf buf;
struct SqlStmt *stmt;
- if( !auction )
- return false;
+ nullpo_ret(auction);
auction->timestamp = time(NULL) + (auction->hours * 3600);
StrBuf->Init(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", auction_db);
- for( j = 0; j < MAX_SLOTS; j++ )
+ for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ",`card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j);
StrBuf->Printf(&buf, ") VALUES ('%d',?,'%d',?,'%d','%d','%d','%lu','%d',?,'%d','%d','%d','%"PRIu64"'",
auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute, auction->item.unique_id);
- for( j = 0; j < MAX_SLOTS; j++ )
+ for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ",'%d'", auction->item.card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ",'%d','%d'", auction->item.option[j].index, auction->item.option[j].value);
+
StrBuf->AppendStr(&buf, ")");
stmt = SQL->StmtMalloc(inter->sql_handle);
- if( SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
+ if (SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, auction->seller_name, strnlen(auction->seller_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, auction->buyer_name, strnlen(auction->buyer_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 2, SQLDT_STRING, auction->item_name, strnlen(auction->item_name, ITEM_NAME_LENGTH))
- || SQL_SUCCESS != SQL->StmtExecute(stmt) )
+ || SQL_SUCCESS != SQL->StmtExecute(stmt))
{
SqlStmt_ShowDebug(stmt);
auction->auction_id = 0;
- }
- else
- {
+ } else {
struct auction_data *auction_;
int64 tick = (int64)auction->hours * 3600000;
@@ -144,17 +148,8 @@ unsigned int inter_auction_create(struct auction_data *auction)
return auction->auction_id;
}
-void mapif_auction_message(int char_id, unsigned char result)
+static int inter_auction_end_timer(int tid, int64 tick, int id, intptr_t data)
{
- unsigned char buf[74];
-
- WBUFW(buf,0) = 0x3854;
- WBUFL(buf,2) = char_id;
- WBUFL(buf,6) = result;
- mapif->sendall(buf,7);
-}
-
-static int inter_auction_end_timer(int tid, int64 tick, int id, intptr_t data) {
struct auction_data *auction;
if( (auction = (struct auction_data *)idb_get(inter_auction->db, id)) != NULL )
{
@@ -176,7 +171,7 @@ static int inter_auction_end_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-void inter_auction_delete(struct auction_data *auction)
+static void inter_auction_delete(struct auction_data *auction)
{
unsigned int auction_id;
nullpo_retv(auction);
@@ -192,7 +187,7 @@ void inter_auction_delete(struct auction_data *auction)
idb_remove(inter_auction->db, auction_id);
}
-void inter_auctions_fromsql(void)
+static void inter_auctions_fromsql(void)
{
int i;
struct auction_data *auction;
@@ -204,8 +199,10 @@ void inter_auctions_fromsql(void)
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `auction_id`,`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,"
"`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`");
- for( i = 0; i < MAX_SLOTS; i++ )
+ for (i = 0; i < MAX_SLOTS; i++)
StrBuf->Printf(&buf, ",`card%d`", i);
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
StrBuf->Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db);
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
@@ -238,14 +235,20 @@ void inter_auctions_fromsql(void)
item->identify = 1;
item->amount = 1;
item->expire_time = 0;
-
- for( i = 0; i < MAX_SLOTS; i++ )
- {
+ /* Card Slots */
+ for (i = 0; i < MAX_SLOTS; i++) {
SQL->GetData(inter->sql_handle, 15 + i, &data, NULL);
item->card[i] = atoi(data);
}
+ /* Item Options */
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ SQL->GetData(inter->sql_handle, 15 + MAX_SLOTS + i * 2, &data, NULL);
+ item->option[i].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 16 + MAX_SLOTS + i * 2, &data, NULL);
+ item->option[i].value = atoi(data);
+ }
- if( auction->timestamp > now )
+ if (auction->timestamp > now)
endtick = ((int64)(auction->timestamp - now) * 1000) + tick;
else
endtick = tick + 10000; // 10 seconds to process ended auctions
@@ -257,235 +260,10 @@ void inter_auctions_fromsql(void)
SQL->FreeResult(inter->sql_handle);
}
-void mapif_auction_sendlist(int fd, int char_id, short count, short pages, unsigned char *buf)
-{
- int len = (sizeof(struct auction_data) * count) + 12;
-
- nullpo_retv(buf);
-
- WFIFOHEAD(fd, len);
- WFIFOW(fd,0) = 0x3850;
- WFIFOW(fd,2) = len;
- WFIFOL(fd,4) = char_id;
- WFIFOW(fd,8) = count;
- WFIFOW(fd,10) = pages;
- memcpy(WFIFOP(fd,12), buf, len - 12);
- WFIFOSET(fd,len);
-}
-
-void mapif_parse_auction_requestlist(int fd)
-{
- char searchtext[NAME_LENGTH];
- int char_id = RFIFOL(fd,4), len = sizeof(struct auction_data);
- int price = RFIFOL(fd,10);
- short type = RFIFOW(fd,8), page = max(1,RFIFOW(fd,14));
- unsigned char buf[5 * sizeof(struct auction_data)];
- struct DBIterator *iter = db_iterator(inter_auction->db);
- struct auction_data *auction;
- short i = 0, j = 0, pages = 1;
-
- memcpy(searchtext, RFIFOP(fd,16), NAME_LENGTH);
-
- for( auction = dbi_first(iter); dbi_exists(iter); auction = dbi_next(iter) )
- {
- if( (type == 0 && auction->type != IT_ARMOR && auction->type != IT_PETARMOR) ||
- (type == 1 && auction->type != IT_WEAPON) ||
- (type == 2 && auction->type != IT_CARD) ||
- (type == 3 && auction->type != IT_ETC) ||
- (type == 4 && !strstr(auction->item_name, searchtext)) ||
- (type == 5 && auction->price > price) ||
- (type == 6 && auction->seller_id != char_id) ||
- (type == 7 && auction->buyer_id != char_id) )
- continue;
-
- i++;
- if( i > 5 )
- { // Counting Pages of Total Results (5 Results per Page)
- pages++;
- i = 1; // First Result of This Page
- }
-
- if( page != pages )
- continue; // This is not the requested Page
-
- memcpy(WBUFP(buf, j * len), auction, len);
- j++; // Found Results
- }
- dbi_destroy(iter);
-
- mapif->auction_sendlist(fd, char_id, j, pages, buf);
-}
-
-void mapif_auction_register(int fd, struct auction_data *auction)
-{
- int len = sizeof(struct auction_data) + 4;
-
- nullpo_retv(auction);
-
- WFIFOHEAD(fd,len);
- WFIFOW(fd,0) = 0x3851;
- WFIFOW(fd,2) = len;
- memcpy(WFIFOP(fd,4), auction, sizeof(struct auction_data));
- WFIFOSET(fd,len);
-}
-
-void mapif_parse_auction_register(int fd)
-{
- struct auction_data auction;
- if( RFIFOW(fd,2) != sizeof(struct auction_data) + 4 )
- return;
-
- memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data));
- if( inter_auction->count(auction.seller_id, false) < 5 )
- auction.auction_id = inter_auction->create(&auction);
-
- mapif->auction_register(fd, &auction);
-}
-
-void mapif_auction_cancel(int fd, int char_id, unsigned char result)
-{
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x3852;
- WFIFOL(fd,2) = char_id;
- WFIFOB(fd,6) = result;
- WFIFOSET(fd,7);
-}
-
-void mapif_parse_auction_cancel(int fd)
-{
- int char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6);
- struct auction_data *auction;
-
- if( (auction = (struct auction_data *)idb_get(inter_auction->db, auction_id)) == NULL )
- {
- mapif->auction_cancel(fd, char_id, 1); // Bid Number is Incorrect
- return;
- }
-
- if( auction->seller_id != char_id )
- {
- mapif->auction_cancel(fd, char_id, 2); // You cannot end the auction
- return;
- }
-
- if( auction->buyer_id > 0 )
- {
- mapif->auction_cancel(fd, char_id, 3); // An auction with at least one bidder cannot be canceled
- return;
- }
-
- inter_mail->sendmail(0, "Auction Manager", auction->seller_id, auction->seller_name, "Auction", "Auction canceled.", 0, &auction->item);
- inter_auction->delete_(auction);
-
- mapif->auction_cancel(fd, char_id, 0); // The auction has been canceled
-}
-
-void mapif_auction_close(int fd, int char_id, unsigned char result)
-{
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x3853;
- WFIFOL(fd,2) = char_id;
- WFIFOB(fd,6) = result;
- WFIFOSET(fd,7);
-}
-
-void mapif_parse_auction_close(int fd)
-{
- int char_id = RFIFOL(fd,2), auction_id = RFIFOL(fd,6);
- struct auction_data *auction;
-
- if( (auction = (struct auction_data *)idb_get(inter_auction->db, auction_id)) == NULL )
- {
- mapif->auction_close(fd, char_id, 2); // Bid Number is Incorrect
- return;
- }
-
- if( auction->seller_id != char_id )
- {
- mapif->auction_close(fd, char_id, 1); // You cannot end the auction
- return;
- }
-
- if( auction->buyer_id == 0 )
- {
- mapif->auction_close(fd, char_id, 1); // You cannot end the auction
- return;
- }
-
- // Send Money to Seller
- inter_mail->sendmail(0, "Auction Manager", auction->seller_id, auction->seller_name, "Auction", "Auction closed.", auction->price, NULL);
- // Send Item to Buyer
- inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "Auction winner.", 0, &auction->item);
- mapif->auction_message(auction->buyer_id, 6); // You have won the auction
- inter_auction->delete_(auction);
-
- mapif->auction_close(fd, char_id, 0); // You have ended the auction
-}
-
-void mapif_auction_bid(int fd, int char_id, int bid, unsigned char result)
-{
- WFIFOHEAD(fd,11);
- WFIFOW(fd,0) = 0x3855;
- WFIFOL(fd,2) = char_id;
- WFIFOL(fd,6) = bid; // To Return Zeny
- WFIFOB(fd,10) = result;
- WFIFOSET(fd,11);
-}
-
-void mapif_parse_auction_bid(int fd)
-{
- int char_id = RFIFOL(fd,4), bid = RFIFOL(fd,12);
- unsigned int auction_id = RFIFOL(fd,8);
- struct auction_data *auction;
-
- if( (auction = (struct auction_data *)idb_get(inter_auction->db, auction_id)) == NULL || auction->price >= bid || auction->seller_id == char_id )
- {
- mapif->auction_bid(fd, char_id, bid, 0); // You have failed to bid in the auction
- return;
- }
-
- if( inter_auction->count(char_id, true) > 4 && bid < auction->buynow && auction->buyer_id != char_id )
- {
- mapif->auction_bid(fd, char_id, bid, 9); // You cannot place more than 5 bids at a time
- return;
- }
-
- if( auction->buyer_id > 0 )
- { // Send Money back to the previous Buyer
- if( auction->buyer_id != char_id )
- {
- inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "Someone has placed a higher bid.", auction->price, NULL);
- mapif->auction_message(auction->buyer_id, 7); // You have failed to win the auction
- }
- else
- inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "You have placed a higher bid.", auction->price, NULL);
- }
-
- auction->buyer_id = char_id;
- safestrncpy(auction->buyer_name, RFIFOP(fd,16), NAME_LENGTH);
- auction->price = bid;
-
- if( bid >= auction->buynow )
- { // Automatic won the auction
- mapif->auction_bid(fd, char_id, bid - auction->buynow, 1); // You have successfully bid in the auction
-
- inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "You have won the auction.", 0, &auction->item);
- mapif->auction_message(char_id, 6); // You have won the auction
- inter_mail->sendmail(0, "Auction Manager", auction->seller_id, auction->seller_name, "Auction", "Payment for your auction!.", auction->buynow, NULL);
-
- inter_auction->delete_(auction);
- return;
- }
-
- inter_auction->save(auction);
-
- mapif->auction_bid(fd, char_id, 0, 1); // You have successfully bid in the auction
-}
-
/*==========================================
* Packets From Map Server
*------------------------------------------*/
-int inter_auction_parse_frommap(int fd)
+static int inter_auction_parse_frommap(int fd)
{
switch(RFIFOW(fd,0))
{
@@ -500,7 +278,7 @@ int inter_auction_parse_frommap(int fd)
return 1;
}
-int inter_auction_sql_init(void)
+static int inter_auction_sql_init(void)
{
inter_auction->db = idb_alloc(DB_OPT_RELEASE_DATA);
inter_auction->fromsql();
@@ -508,7 +286,7 @@ int inter_auction_sql_init(void)
return 0;
}
-void inter_auction_sql_final(void)
+static void inter_auction_sql_final(void)
{
inter_auction->db->destroy(inter_auction->db,NULL);
diff --git a/src/char/int_auction.h b/src/char/int_auction.h
index 9f0ccbd09..720efe22a 100644
--- a/src/char/int_auction.h
+++ b/src/char/int_auction.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
diff --git a/src/char/int_clan.c b/src/char/int_clan.c
new file mode 100644
index 000000000..9fb8ad95e
--- /dev/null
+++ b/src/char/int_clan.c
@@ -0,0 +1,155 @@
+/**
+ * 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>
+
+static 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
+ */
+static 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
+ */
+static 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;
+}
+
+// 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
+static 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_elemental.c b/src/char/int_elemental.c
index aed25febd..175007b66 100644
--- a/src/char/int_elemental.c
+++ b/src/char/int_elemental.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -37,7 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_elemental_interface inter_elemental_s;
+static struct inter_elemental_interface inter_elemental_s;
struct inter_elemental_interface *inter_elemental;
/**
@@ -50,7 +50,7 @@ struct inter_elemental_interface *inter_elemental;
* @param[in,out] ele The new elemental's data.
* @retval false in case of errors.
*/
-bool mapif_elemental_create(struct s_elemental *ele)
+static bool inter_elemental_create(struct s_elemental *ele)
{
nullpo_retr(false, ele);
Assert_retr(false, ele->elemental_id == 0);
@@ -73,7 +73,7 @@ bool mapif_elemental_create(struct s_elemental *ele)
* @param ele The elemental's data.
* @retval false in case of errors.
*/
-bool mapif_elemental_save(const struct s_elemental *ele)
+static bool inter_elemental_save(const struct s_elemental *ele)
{
nullpo_retr(false, ele);
Assert_retr(false, ele->elemental_id > 0);
@@ -90,7 +90,8 @@ bool mapif_elemental_save(const struct s_elemental *ele)
return true;
}
-bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) {
+static bool inter_elemental_load(int ele_id, int char_id, struct s_elemental *ele)
+{
char* data;
nullpo_retr(false, ele);
@@ -134,7 +135,8 @@ bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) {
return true;
}
-bool mapif_elemental_delete(int ele_id) {
+static bool inter_elemental_delete(int ele_id)
+{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `ele_id` = '%d'", elemental_db, ele_id) ) {
Sql_ShowDebug(inter->sql_handle);
return false;
@@ -143,72 +145,21 @@ bool mapif_elemental_delete(int ele_id) {
return true;
}
-void mapif_elemental_send(int fd, struct s_elemental *ele, unsigned char flag) {
- int size = sizeof(struct s_elemental) + 5;
-
- nullpo_retv(ele);
- WFIFOHEAD(fd,size);
- WFIFOW(fd,0) = 0x387c;
- WFIFOW(fd,2) = size;
- WFIFOB(fd,4) = flag;
- memcpy(WFIFOP(fd,5),ele,sizeof(struct s_elemental));
- WFIFOSET(fd,size);
-}
-
-void mapif_parse_elemental_create(int fd, const struct s_elemental *ele)
+static void inter_elemental_sql_init(void)
{
- struct s_elemental ele_;
- bool result;
-
- memcpy(&ele_, ele, sizeof(ele_));
-
- result = mapif->elemental_create(&ele_);
- mapif->elemental_send(fd, &ele_, result);
-}
-
-void mapif_parse_elemental_load(int fd, int ele_id, int char_id) {
- struct s_elemental ele;
- bool result = mapif->elemental_load(ele_id, char_id, &ele);
- mapif->elemental_send(fd, &ele, result);
-}
-
-void mapif_elemental_deleted(int fd, unsigned char flag) {
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x387d;
- WFIFOB(fd,2) = flag;
- WFIFOSET(fd,3);
-}
-
-void mapif_parse_elemental_delete(int fd, int ele_id) {
- bool result = mapif->elemental_delete(ele_id);
- mapif->elemental_deleted(fd, result);
-}
-
-void mapif_elemental_saved(int fd, unsigned char flag) {
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x387e;
- WFIFOB(fd,2) = flag;
- WFIFOSET(fd,3);
-}
-
-void mapif_parse_elemental_save(int fd, const struct s_elemental *ele)
-{
- bool result = mapif->elemental_save(ele);
- mapif->elemental_saved(fd, result);
-}
-
-void inter_elemental_sql_init(void) {
return;
}
-void inter_elemental_sql_final(void) {
+static void inter_elemental_sql_final(void)
+{
return;
}
/*==========================================
* Inter Packets
*------------------------------------------*/
-int inter_elemental_parse_frommap(int fd) {
+static int inter_elemental_parse_frommap(int fd)
+{
unsigned short cmd = RFIFOW(fd,0);
switch (cmd) {
@@ -229,4 +180,9 @@ void inter_elemental_defaults(void)
inter_elemental->sql_init = inter_elemental_sql_init;
inter_elemental->sql_final = inter_elemental_sql_final;
inter_elemental->parse_frommap = inter_elemental_parse_frommap;
+
+ inter_elemental->create = inter_elemental_create;
+ inter_elemental->save = inter_elemental_save;
+ inter_elemental->load = inter_elemental_load;
+ inter_elemental->delete = inter_elemental_delete;
}
diff --git a/src/char/int_elemental.h b/src/char/int_elemental.h
index 8a046b0f8..3172dcacf 100644
--- a/src/char/int_elemental.h
+++ b/src/char/int_elemental.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#define CHAR_INT_ELEMENTAL_H
#include "common/hercules.h"
+#include "common/mmo.h"
/**
* inter_elemental_interface interface
@@ -30,6 +31,11 @@ struct inter_elemental_interface {
void (*sql_init) (void);
void (*sql_final) (void);
int (*parse_frommap) (int fd);
+
+ bool (*create) (struct s_elemental *ele);
+ bool (*save) (const struct s_elemental *ele);
+ bool (*load) (int ele_id, int char_id, struct s_elemental *ele);
+ bool (*delete) (int ele_id);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_guild.c b/src/char/int_guild.c
index b4b4bdde4..56e1c1ba3 100644
--- a/src/char/int_guild.c
+++ b/src/char/int_guild.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -51,12 +51,13 @@
#define GUILD_ALLIANCE_TYPE_MASK 0x01
#define GUILD_ALLIANCE_REMOVE 0x08
-struct inter_guild_interface inter_guild_s;
+static struct inter_guild_interface inter_guild_s;
struct inter_guild_interface *inter_guild;
static const char dataToHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-int inter_guild_save_timer(int tid, int64 tick, int id, intptr_t data) {
+static int inter_guild_save_timer(int tid, int64 tick, int id, intptr_t data)
+{
static int last_id = 0; //To know in which guild we were.
int state = 0; //0: Have not reached last guild. 1: Reached last guild, ready for save. 2: Some guild saved, don't do further saving.
struct DBIterator *iter = db_iterator(inter_guild->guild_db);
@@ -101,7 +102,7 @@ int inter_guild_save_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int inter_guild_removemember_tosql(int account_id, int char_id)
+static int inter_guild_removemember_tosql(int account_id, int char_id)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", guild_member_db, account_id, char_id) )
Sql_ShowDebug(inter->sql_handle);
@@ -111,7 +112,7 @@ int inter_guild_removemember_tosql(int account_id, int char_id)
}
// Save guild into sql
-int inter_guild_tosql(struct guild *g,int flag)
+static int inter_guild_tosql(struct guild *g, int flag)
{
// Table guild (GS_BASIC_MASK)
// GS_EMBLEM `emblem_len`,`emblem_id`,`emblem_data`
@@ -138,7 +139,7 @@ int inter_guild_tosql(struct guild *g,int flag)
if (g->guild_id<=0 && g->guild_id != -1) return 0;
#ifdef NOISY
- ShowInfo("Save guild request ("CL_BOLD"%d"CL_RESET" - flag 0x%x).",g->guild_id, flag);
+ ShowInfo("Save guild request ("CL_BOLD"%d"CL_RESET" - flag 0x%x).\n",g->guild_id, flag);
#endif
SQL->EscapeStringLen(inter->sql_handle, esc_name, g->name, strnlen(g->name, NAME_LENGTH));
@@ -343,7 +344,7 @@ int inter_guild_tosql(struct guild *g,int flag)
}
// Read guild from sql
-struct guild * inter_guild_fromsql(int guild_id)
+static struct guild *inter_guild_fromsql(int guild_id)
{
struct guild *g;
char* data;
@@ -417,8 +418,8 @@ struct guild * inter_guild_fromsql(int guild_id)
}
// load guild member info
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` "
- "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) )
+ if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT g.`account_id`,g.`char_id`,g.`hair`,g.`hair_color`,g.`gender`,g.`class`,g.`lv`,g.`exp`,g.`exp_payper`,g.`online`,g.`position`,g.`name`,c.`last_login`"
+ "FROM `%s` g LEFT JOIN `%s` c ON c.`char_id` = g.`char_id` WHERE g.`guild_id`='%d' ORDER BY `position`", guild_member_db, char_db, guild_id) )
{
Sql_ShowDebug(inter->sql_handle);
aFree(g);
@@ -442,6 +443,9 @@ struct guild * inter_guild_fromsql(int guild_id)
if( m->position >= MAX_GUILDPOSITION ) // Fix reduction of MAX_GUILDPOSITION [PoW]
m->position = MAX_GUILDPOSITION - 1;
SQL->GetData(inter->sql_handle, 11, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
+ SQL->GetData(inter->sql_handle, 12, &data, NULL);
+ if (data != NULL)
+ m->last_login = atoi(data);
m->modified = GS_MEMBER_UNMODIFIED;
}
@@ -532,7 +536,7 @@ struct guild * inter_guild_fromsql(int guild_id)
}
// `guild_castle` (`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, `visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`)
-int inter_guild_castle_tosql(struct guild_castle *gc)
+static int inter_guild_castle_tosql(struct guild_castle *gc)
{
StringBuf buf;
int i;
@@ -556,7 +560,7 @@ int inter_guild_castle_tosql(struct guild_castle *gc)
}
// Read guild_castle from SQL
-struct guild_castle* inter_guild_castle_fromsql(int castle_id)
+static struct guild_castle *inter_guild_castle_fromsql(int castle_id)
{
char *data;
int i;
@@ -608,7 +612,8 @@ struct guild_castle* inter_guild_castle_fromsql(int castle_id)
// Read exp_guild.txt
-bool inter_guild_exp_parse_row(char* split[], int column, int current) {
+static bool inter_guild_exp_parse_row(char *split[], int column, int current)
+{
int64 exp = strtoll(split[0], NULL, 10);
nullpo_retr(true, split);
@@ -622,7 +627,8 @@ bool inter_guild_exp_parse_row(char* split[], int column, int current) {
}
-int inter_guild_CharOnline(int char_id, int guild_id) {
+static int inter_guild_CharOnline(int char_id, int guild_id)
+{
struct guild *g;
int i;
@@ -671,7 +677,7 @@ int inter_guild_CharOnline(int char_id, int guild_id) {
return 1;
}
-int inter_guild_CharOffline(int char_id, int guild_id)
+static int inter_guild_CharOffline(int char_id, int guild_id)
{
struct guild *g=NULL;
int online_count, i;
@@ -727,7 +733,7 @@ int inter_guild_CharOffline(int char_id, int guild_id)
}
// Initialize guild sql
-int inter_guild_sql_init(void)
+static int inter_guild_sql_init(void)
{
//Initialize the guild cache
inter_guild->guild_db= idb_alloc(DB_OPT_RELEASE_DATA);
@@ -744,7 +750,7 @@ int inter_guild_sql_init(void)
/**
* @see DBApply
*/
-int inter_guild_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int inter_guild_db_final(union DBKey key, struct DBData *data, va_list ap)
{
struct guild *g = DB->data2ptr(data);
nullpo_ret(g);
@@ -755,7 +761,7 @@ int inter_guild_db_final(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-void inter_guild_sql_final(void)
+static void inter_guild_sql_final(void)
{
inter_guild->guild_db->destroy(inter_guild->guild_db, inter_guild->db_final);
db_destroy(inter_guild->castle_db);
@@ -763,7 +769,7 @@ void inter_guild_sql_final(void)
}
// Get guild_id by its name. Returns 0 if not found, -1 on error.
-int inter_guild_search_guildname(const char *str)
+static int inter_guild_search_guildname(const char *str)
{
int guild_id;
char esc_name[NAME_LENGTH*2+1];
@@ -806,7 +812,8 @@ static bool inter_guild_check_empty(struct guild *g)
return true;
}
-unsigned int inter_guild_nextexp(int level) {
+static unsigned int inter_guild_nextexp(int level)
+{
if (level == 0)
return 1;
if (level <= 0 || level > MAX_GUILDLEVEL)
@@ -815,7 +822,7 @@ unsigned int inter_guild_nextexp(int level) {
return inter_guild->exp[level-1];
}
-int inter_guild_checkskill(struct guild *g, int id)
+static int inter_guild_checkskill(struct guild *g, int id)
{
int idx = id - GD_SKILLBASE;
@@ -826,7 +833,7 @@ int inter_guild_checkskill(struct guild *g, int id)
return g->skill[idx].lv;
}
-int inter_guild_calcinfo(struct guild *g)
+static int inter_guild_calcinfo(struct guild *g)
{
int i,c;
unsigned int nextexp;
@@ -890,276 +897,7 @@ int inter_guild_calcinfo(struct guild *g)
return 0;
}
-//-------------------------------------------------------------------
-// Packet sent to map server
-
-int mapif_guild_created(int fd, int account_id, struct guild *g)
-{
- WFIFOHEAD(fd, 10);
- WFIFOW(fd,0)=0x3830;
- WFIFOL(fd,2)=account_id;
- if(g != NULL)
- {
- WFIFOL(fd,6)=g->guild_id;
- ShowInfo("int_guild: Guild created (%d - %s)\n",g->guild_id,g->name);
- } else
- WFIFOL(fd,6)=0;
-
- WFIFOSET(fd,10);
- return 0;
-}
-
-// Guild not found
-int mapif_guild_noinfo(int fd, int guild_id)
-{
- unsigned char buf[12];
- WBUFW(buf,0)=0x3831;
- WBUFW(buf,2)=8;
- WBUFL(buf,4)=guild_id;
- ShowWarning("int_guild: info not found %d\n",guild_id);
- if(fd<0)
- mapif->sendall(buf,8);
- else
- mapif->send(fd,buf,8);
- return 0;
-}
-
-// Send guild info
-int mapif_guild_info(int fd, struct guild *g)
-{
- unsigned char buf[8+sizeof(struct guild)];
- nullpo_ret(g);
- WBUFW(buf,0)=0x3831;
- WBUFW(buf,2)=4+sizeof(struct guild);
- memcpy(buf+4,g,sizeof(struct guild));
- if(fd<0)
- mapif->sendall(buf,WBUFW(buf,2));
- else
- mapif->send(fd,buf,WBUFW(buf,2));
- return 0;
-}
-
-// ACK member add
-int mapif_guild_memberadded(int fd, int guild_id, int account_id, int char_id, int flag)
-{
- WFIFOHEAD(fd, 15);
- WFIFOW(fd,0)=0x3832;
- WFIFOL(fd,2)=guild_id;
- WFIFOL(fd,6)=account_id;
- WFIFOL(fd,10)=char_id;
- WFIFOB(fd,14)=flag;
- WFIFOSET(fd,15);
- return 0;
-}
-
-// ACK member leave
-int mapif_guild_withdraw(int guild_id,int account_id,int char_id,int flag, const char *name, const char *mes)
-{
- unsigned char buf[55+NAME_LENGTH];
-
- nullpo_ret(name);
- nullpo_ret(mes);
-
- WBUFW(buf, 0)=0x3834;
- WBUFL(buf, 2)=guild_id;
- WBUFL(buf, 6)=account_id;
- WBUFL(buf,10)=char_id;
- WBUFB(buf,14)=flag;
- memcpy(WBUFP(buf,15),mes,40);
- memcpy(WBUFP(buf,55),name,NAME_LENGTH);
- mapif->sendall(buf,55+NAME_LENGTH);
- ShowInfo("int_guild: guild withdraw (%d - %d: %s - %s)\n",guild_id,account_id,name,mes);
- return 0;
-}
-
-// Send short member's info
-int mapif_guild_memberinfoshort(struct guild *g, int idx)
-{
- unsigned char buf[19];
- nullpo_ret(g);
- Assert_ret(idx >= 0 && idx < MAX_GUILD);
- WBUFW(buf, 0)=0x3835;
- WBUFL(buf, 2)=g->guild_id;
- WBUFL(buf, 6)=g->member[idx].account_id;
- WBUFL(buf,10)=g->member[idx].char_id;
- WBUFB(buf,14)=(unsigned char)g->member[idx].online;
- WBUFW(buf,15)=g->member[idx].lv;
- WBUFW(buf,17)=g->member[idx].class;
- mapif->sendall(buf,19);
- return 0;
-}
-
-// Send guild broken
-int mapif_guild_broken(int guild_id, int flag)
-{
- unsigned char buf[7];
- WBUFW(buf,0)=0x3836;
- WBUFL(buf,2)=guild_id;
- WBUFB(buf,6)=flag;
- mapif->sendall(buf,7);
- ShowInfo("int_guild: Guild broken (%d)\n",guild_id);
- return 0;
-}
-
-// Send guild message
-int mapif_guild_message(int guild_id, int account_id, const char *mes, int len, int sfd)
-{
- unsigned char buf[512];
- nullpo_ret(mes);
- if (len > 500)
- len = 500;
- WBUFW(buf,0)=0x3837;
- WBUFW(buf,2)=len+12;
- WBUFL(buf,4)=guild_id;
- WBUFL(buf,8)=account_id;
- memcpy(WBUFP(buf,12),mes,len);
- mapif->sendallwos(sfd, buf,len+12);
- return 0;
-}
-
-// Send basic info
-int mapif_guild_basicinfochanged(int guild_id, int type, const void *data, int len)
-{
- unsigned char buf[2048];
- nullpo_ret(data);
- if (len > 2038)
- len = 2038;
- WBUFW(buf, 0)=0x3839;
- WBUFW(buf, 2)=len+10;
- WBUFL(buf, 4)=guild_id;
- WBUFW(buf, 8)=type;
- memcpy(WBUFP(buf,10),data,len);
- mapif->sendall(buf,len+10);
- return 0;
-}
-
-// Send member info
-int mapif_guild_memberinfochanged(int guild_id, int account_id, int char_id, int type, const void *data, int len)
-{
- unsigned char buf[2048];
- nullpo_ret(data);
- if (len > 2030)
- len = 2030;
- WBUFW(buf, 0)=0x383a;
- WBUFW(buf, 2)=len+18;
- WBUFL(buf, 4)=guild_id;
- WBUFL(buf, 8)=account_id;
- WBUFL(buf,12)=char_id;
- WBUFW(buf,16)=type;
- memcpy(WBUFP(buf,18),data,len);
- mapif->sendall(buf,len+18);
- return 0;
-}
-
-// ACK guild skill up
-int mapif_guild_skillupack(int guild_id, uint16 skill_id, int account_id)
-{
- unsigned char buf[14];
- WBUFW(buf, 0)=0x383c;
- WBUFL(buf, 2)=guild_id;
- WBUFL(buf, 6)=skill_id;
- WBUFL(buf,10)=account_id;
- mapif->sendall(buf,14);
- return 0;
-}
-
-// ACK guild alliance
-int mapif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag, const char *name1, const char *name2)
-{
- unsigned char buf[19+2*NAME_LENGTH];
- nullpo_ret(name1);
- nullpo_ret(name2);
- WBUFW(buf, 0)=0x383d;
- WBUFL(buf, 2)=guild_id1;
- WBUFL(buf, 6)=guild_id2;
- WBUFL(buf,10)=account_id1;
- WBUFL(buf,14)=account_id2;
- WBUFB(buf,18)=flag;
- memcpy(WBUFP(buf,19),name1,NAME_LENGTH);
- memcpy(WBUFP(buf,19+NAME_LENGTH),name2,NAME_LENGTH);
- mapif->sendall(buf,19+2*NAME_LENGTH);
- return 0;
-}
-
-// Send a guild position desc
-int mapif_guild_position(struct guild *g, int idx)
-{
- unsigned char buf[12 + sizeof(struct guild_position)];
- nullpo_ret(g);
- Assert_ret(idx >= 0 && idx < MAX_GUILDPOSITION);
- WBUFW(buf,0)=0x383b;
- WBUFW(buf,2)=sizeof(struct guild_position)+12;
- WBUFL(buf,4)=g->guild_id;
- WBUFL(buf,8)=idx;
- memcpy(WBUFP(buf,12),&g->position[idx],sizeof(struct guild_position));
- mapif->sendall(buf,WBUFW(buf,2));
- return 0;
-}
-
-// Send the guild notice
-int mapif_guild_notice(struct guild *g)
-{
- unsigned char buf[256];
- nullpo_ret(g);
- WBUFW(buf,0)=0x383e;
- WBUFL(buf,2)=g->guild_id;
- memcpy(WBUFP(buf,6),g->mes1,MAX_GUILDMES1);
- memcpy(WBUFP(buf,66),g->mes2,MAX_GUILDMES2);
- mapif->sendall(buf,186);
- return 0;
-}
-
-// Send emblem data
-int mapif_guild_emblem(struct guild *g)
-{
- unsigned char buf[12 + sizeof(g->emblem_data)];
- nullpo_ret(g);
- WBUFW(buf,0)=0x383f;
- WBUFW(buf,2)=g->emblem_len+12;
- WBUFL(buf,4)=g->guild_id;
- WBUFL(buf,8)=g->emblem_id;
- memcpy(WBUFP(buf,12),g->emblem_data,g->emblem_len);
- mapif->sendall(buf,WBUFW(buf,2));
- return 0;
-}
-
-int mapif_guild_master_changed(struct guild *g, int aid, int cid)
-{
- unsigned char buf[14];
- nullpo_ret(g);
- WBUFW(buf,0)=0x3843;
- WBUFL(buf,2)=g->guild_id;
- WBUFL(buf,6)=aid;
- WBUFL(buf,10)=cid;
- mapif->sendall(buf,14);
- return 0;
-}
-
-int mapif_guild_castle_dataload(int fd, int sz, const int *castle_ids)
-{
- struct guild_castle *gc = NULL;
- int num = (sz - 4) / sizeof(int);
- int len = 4 + num * sizeof(*gc);
- int i;
-
- nullpo_ret(castle_ids);
- WFIFOHEAD(fd, len);
- WFIFOW(fd, 0) = 0x3840;
- WFIFOW(fd, 2) = len;
- for (i = 0; i < num; i++) {
- gc = inter_guild->castle_fromsql(*(castle_ids++));
- memcpy(WFIFOP(fd, 4 + i * sizeof(*gc)), gc, sizeof(*gc));
- }
- WFIFOSET(fd, len);
- return 0;
-}
-
-//-------------------------------------------------------------------
-// Packet received from map server
-
-
-// Guild creation request
-int mapif_parse_CreateGuild(int fd, int account_id, const char *name, const struct guild_member *master)
+static struct guild *inter_guild_create(const char *name, const struct guild_member *master)
{
struct guild *g;
int i=0;
@@ -1170,21 +908,18 @@ int mapif_parse_CreateGuild(int fd, int account_id, const char *name, const stru
nullpo_ret(master);
if(inter_guild->search_guildname(name) != 0){
ShowInfo("int_guild: guild with same name exists [%s]\n",name);
- mapif->guild_created(fd,account_id,NULL);
- return 0;
+ return NULL;
}
// Check Authorized letters/symbols in the name of the character
if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorized
for (i = 0; i < NAME_LENGTH && name[i]; i++)
if (strchr(char_name_letters, name[i]) == NULL) {
- mapif->guild_created(fd,account_id,NULL);
- return 0;
+ return NULL;
}
} else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
for (i = 0; i < NAME_LENGTH && name[i]; i++)
if (strchr(char_name_letters, name[i]) != NULL) {
- mapif->guild_created(fd,account_id,NULL);
- return 0;
+ return NULL;
}
}
@@ -1220,108 +955,84 @@ int mapif_parse_CreateGuild(int fd, int account_id, const char *name, const stru
if (!inter_guild->tosql(g,GS_BASIC|GS_POSITION|GS_SKILL|GS_MEMBER)) {
//Failed to Create guild....
ShowError("Failed to create Guild %s (Guild Master: %s)\n", g->name, g->master);
- mapif->guild_created(fd,account_id,NULL);
aFree(g);
- return 0;
+ return NULL;
}
ShowInfo("Created Guild %d - %s (Guild Master: %s)\n", g->guild_id, g->name, g->master);
//Add to cache
idb_put(inter_guild->guild_db, g->guild_id, g);
- // Report to client
- mapif->guild_created(fd,account_id,g);
- mapif->guild_info(fd,g);
-
if (inter->enable_logs)
inter->log("guild %s (id=%d) created by master %s (id=%d)\n",
name, g->guild_id, master->name, master->account_id);
- return 0;
-}
-
-// Return guild info to client
-int mapif_parse_GuildInfo(int fd, int guild_id)
-{
- struct guild * g = inter_guild->fromsql(guild_id); //We use this because on start-up the info of castle-owned guilds is required. [Skotlex]
- if(g)
- {
- if (!inter_guild->calcinfo(g))
- mapif->guild_info(fd,g);
- }
- else
- mapif->guild_noinfo(fd,guild_id); // Failed to load info
- return 0;
+ return g;
}
// Add member to guild
-int mapif_parse_GuildAddMember(int fd, int guild_id, const struct guild_member *m)
+static bool inter_guild_add_member(int guild_id, const struct guild_member *member, int map_fd)
{
struct guild * g;
int i;
+ nullpo_ret(member);
- nullpo_ret(m);
g = inter_guild->fromsql(guild_id);
- if(g==NULL){
- mapif->guild_memberadded(fd,guild_id,m->account_id,m->char_id,1); // 1: Failed to add
- return 0;
+ if (g == NULL) {
+ mapif->guild_memberadded(map_fd, guild_id, member->account_id, member->char_id, 1); // 1: Failed to add
+ return false;
}
// Find an empty slot
- for(i=0;i<g->max_member;i++)
- {
- if(g->member[i].account_id==0)
- {
- memcpy(&g->member[i],m,sizeof(struct guild_member));
+ for (i = 0; i < g->max_member; i++) {
+ if (g->member[i].account_id == 0) {
+ g->member[i] = *member;
g->member[i].modified = (GS_MEMBER_NEW | GS_MEMBER_MODIFIED);
- mapif->guild_memberadded(fd,guild_id,m->account_id,m->char_id,0); // 0: success
+ mapif->guild_memberadded(map_fd, guild_id, member->account_id, member->char_id, 0); // 0: success
if (!inter_guild->calcinfo(g)) //Send members if it was not invoked.
- mapif->guild_info(-1,g);
+ mapif->guild_info(-1, g);
g->save_flag |= GS_MEMBER;
if (g->save_flag&GS_REMOVE)
g->save_flag&=~GS_REMOVE;
- return 0;
+ return true;
}
}
- mapif->guild_memberadded(fd,guild_id,m->account_id,m->char_id,1); // 1: Failed to add
- return 0;
+ mapif->guild_memberadded(map_fd, guild_id, member->account_id, member->char_id, 1); // 1: Failed to add
+ return false;
}
// Delete member from guild
-int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes)
+static bool inter_guild_leave(int guild_id, int account_id, int char_id, int flag, const char *mes, int map_fd)
{
int i;
- struct guild* g = inter_guild->fromsql(guild_id);
- if( g == NULL )
- {
+ struct guild *g = inter_guild->fromsql(guild_id);
+ if (g == NULL) {
// Unknown guild, just update the player
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id))
Sql_ShowDebug(inter->sql_handle);
// mapif->guild_withdraw(guild_id,account_id,char_id,flag,g->member[i].name,mes);
- return 0;
+ return false;
}
nullpo_ret(mes);
// Find the member
- ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
- if( i == g->max_member )
- {
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id);
+ if (i == g->max_member) {
//TODO
- return 0;
+ return false;
}
if (flag) {
// Write expulsion reason
// Find an empty slot
int j;
- ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 );
- if( j == MAX_GUILDEXPULSION )
- {
+ ARR_FIND(0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0);
+ if (j == MAX_GUILDEXPULSION) {
// Expulsion list is full, flush the oldest one
- for( j = 0; j < MAX_GUILDEXPULSION - 1; j++ )
+ for (j = 0; j < MAX_GUILDEXPULSION - 1; j++)
g->expulsion[j] = g->expulsion[j+1];
j = MAX_GUILDEXPULSION-1;
}
@@ -1336,38 +1047,38 @@ int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, in
memset(&g->member[i],0,sizeof(struct guild_member));
- if( inter_guild->check_empty(g) )
- mapif->parse_BreakGuild(-1,guild_id); //Break the guild.
- else {
+ if (inter_guild->check_empty(g)) {
+ inter_guild->disband(guild_id);
+ } else {
//Update member info.
if (!inter_guild->calcinfo(g))
- mapif->guild_info(fd,g);
+ mapif->guild_info(map_fd,g);
g->save_flag |= GS_EXPULSION;
}
- return 0;
+ return true;
}
// Change member info
-int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id, int char_id, int online, int lv, int16 class)
+static bool inter_guild_update_member_info_short(int guild_id, int account_id, int char_id, int online, int lv, int16 class)
{
// Could speed up by manipulating only guild_member
- struct guild * g;
+ struct guild *g;
int i,sum,c;
int prev_count, prev_alv;
g = inter_guild->fromsql(guild_id);
- if(g==NULL)
- return 0;
+ if (g == NULL)
+ return false;
- ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
- if( i < g->max_member )
- {
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id);
+ if (i < g->max_member) {
g->member[i].online = online;
g->member[i].lv = lv;
g->member[i].class = class;
+ g->member[i].last_login = (uint32)time(NULL);
g->member[i].modified = GS_MEMBER_MODIFIED;
- mapif->guild_memberinfoshort(g,i);
+ mapif->guild_memberinfoshort(g, i);
}
prev_count = g->connect_member;
@@ -1378,99 +1089,90 @@ int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id,
c = 0;
sum = 0;
- for( i = 0; i < g->max_member; i++ )
- {
- if( g->member[i].account_id > 0 )
- {
+ for (i = 0; i < g->max_member; i++) {
+ if (g->member[i].account_id > 0) {
sum += g->member[i].lv;
c++;
}
- if( g->member[i].online )
+ if (g->member[i].online)
g->connect_member++;
}
- if( c ) // this check should always succeed...
- {
+ if (c != 0) { // this check should always succeed...
g->average_lv = sum / c;
- if( g->connect_member != prev_count || g->average_lv != prev_alv )
+ if (g->connect_member != prev_count || g->average_lv != prev_alv)
g->save_flag |= GS_CONNECT;
- if( g->save_flag & GS_REMOVE )
+ if (g->save_flag & GS_REMOVE)
g->save_flag &= ~GS_REMOVE;
}
g->save_flag |= GS_MEMBER; //Update guild member data
- return 0;
+ return true;
}
// BreakGuild
-int mapif_parse_BreakGuild(int fd, int guild_id)
+static bool inter_guild_disband(int guild_id)
{
- struct guild * g;
-
- g = inter_guild->fromsql(guild_id);
- if(g==NULL)
- return 0;
+ struct guild *g = inter_guild->fromsql(guild_id);
+ if (g == NULL)
+ return false;
// Delete guild from sql
//printf("- Delete guild %d from guild\n",guild_id);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id))
Sql_ShowDebug(inter->sql_handle);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
//printf("- Update guild %d of char\n",guild_id);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", char_db, guild_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", char_db, guild_id))
Sql_ShowDebug(inter->sql_handle);
- mapif->guild_broken(guild_id,0);
+ mapif->guild_broken(guild_id, 0);
if (inter->enable_logs)
inter->log("guild %s (id=%d) broken\n", g->name, guild_id);
//Remove the guild from memory. [Skotlex]
idb_remove(inter_guild->guild_db, guild_id);
- return 0;
-}
-// Forward Guild message to others map servers
-int mapif_parse_GuildMessage(int fd, int guild_id, int account_id, const char *mes, int len)
-{
- return mapif->guild_message(guild_id,account_id,mes,len, fd);
+ return true;
}
/**
* Changes basic guild information
* The types are available in mmo.h::guild_basic_info
**/
-int mapif_parse_GuildBasicInfoChange(int fd, int guild_id, int type, const void *data, int len) {
+static bool inter_guild_update_basic_info(int guild_id, int type, const void *data, int len)
+{
struct guild *g;
struct guild_skill gd_skill;
short value;
g = inter_guild->fromsql(guild_id);
- if( g == NULL )
- return 0;
+ if (g == NULL)
+ return false;
nullpo_ret(data);
- switch(type) {
+ switch (type) {
case GBI_EXP:
value = *((const int16 *)data);
if( value < 0 && abs(value) > g->exp )
@@ -1506,26 +1208,25 @@ int mapif_parse_GuildBasicInfoChange(int fd, int guild_id, int type, const void
default:
ShowError("int_guild: GuildBasicInfoChange: Unknown type %d, see mmo.h::guild_basic_info for more information\n",type);
- return 0;
+ return false;
}
mapif->guild_info(-1,g);
g->save_flag |= GS_LEVEL;
- // Information is already sent in mapif->guild_info
- //mapif->guild_basicinfochanged(guild_id,type,data,len);
- return 0;
+
+ return true;
}
// Modification of the guild
-int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int char_id, int type, const char *data, int len)
+static bool inter_guild_update_member_info(int guild_id, int account_id, int char_id, int type, const char *data, int len)
{
// Could make some improvement in speed, because only change guild_member
int i;
- struct guild * g;
+ struct guild *g;
nullpo_ret(data);
g = inter_guild->fromsql(guild_id);
if(g==NULL)
- return 0;
+ return false;
// Search the member
for (i = 0; i < g->max_member; i++) {
@@ -1537,7 +1238,7 @@ int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int
if(i==g->max_member){
ShowWarning("int_guild: GuildMemberChange: Not found %d,%d in guild (%d - %s)\n",
account_id,char_id,guild_id,g->name);
- return 0;
+ return false;
}
switch(type)
@@ -1618,17 +1319,18 @@ int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int
}
default:
ShowError("int_guild: GuildMemberInfoChange: Unknown type %d\n",type);
+ return false;
break;
}
- return 0;
+ return true;
}
-int inter_guild_sex_changed(int guild_id, int account_id, int char_id, short gender)
+static int inter_guild_sex_changed(int guild_id, int account_id, int char_id, short gender)
{
- return mapif->parse_GuildMemberInfoChange(0, guild_id, account_id, char_id, GMI_GENDER, (const char*)&gender, sizeof(gender));
+ return inter_guild->update_member_info(guild_id, account_id, char_id, GMI_GENDER, (const char*)&gender, sizeof(gender));
}
-int inter_guild_charname_changed(int guild_id, int account_id, int char_id, char *name)
+static int inter_guild_charname_changed(int guild_id, int account_id, int char_id, char *name)
{
struct guild *g;
int i, flag = 0;
@@ -1666,35 +1368,34 @@ int inter_guild_charname_changed(int guild_id, int account_id, int char_id, char
}
// Change a position desc
-int mapif_parse_GuildPosition(int fd, int guild_id, int idx, const struct guild_position *p)
+static bool inter_guild_update_position(int guild_id, int idx, const struct guild_position *p)
{
// Could make some improvement in speed, because only change guild_position
- struct guild * g;
+ struct guild *g;
nullpo_ret(p);
g = inter_guild->fromsql(guild_id);
if(g==NULL || idx<0 || idx>=MAX_GUILDPOSITION)
- return 0;
+ return false;
memcpy(&g->position[idx],p,sizeof(struct guild_position));
mapif->guild_position(g,idx);
g->position[idx].modified = GS_POSITION_MODIFIED;
g->save_flag |= GS_POSITION; // Change guild_position
- return 0;
+ return true;
}
// Guild Skill UP
-int mapif_parse_GuildSkillUp(int fd, int guild_id, uint16 skill_id, int account_id, int max)
+static bool inter_guild_use_skill_point(int guild_id, uint16 skill_id, int account_id, int max)
{
struct guild * g;
int idx = skill_id - GD_SKILLBASE;
g = inter_guild->fromsql(guild_id);
if(g == NULL || idx < 0 || idx >= MAX_GUILDSKILL)
- return 0;
+ return false;
- if(g->skill_point>0 && g->skill[idx].id>0 && g->skill[idx].lv<max )
- {
+ if (g->skill_point > 0 && g->skill[idx].id > 0 && g->skill[idx].lv < max) {
g->skill[idx].lv++;
g->skill_point--;
if (!inter_guild->calcinfo(g))
@@ -1702,11 +1403,11 @@ int mapif_parse_GuildSkillUp(int fd, int guild_id, uint16 skill_id, int account_
mapif->guild_skillupack(guild_id,skill_id,account_id);
g->save_flag |= (GS_LEVEL|GS_SKILL); // Change guild & guild_skill
}
- return 0;
+ return true;
}
//Manual deletion of an alliance when partnering guild does not exists. [Skotlex]
-int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, int account_id1, int account_id2, int flag)
+static bool inter_guild_remove_alliance(struct guild *g, int guild_id, int account_id1, int account_id2, int flag)
{
int i;
char name[NAME_LENGTH];
@@ -1714,18 +1415,18 @@ int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, int account_i
nullpo_retr(-1, g);
ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id );
if( i == MAX_GUILDALLIANCE )
- return -1;
+ return false;
strcpy(name, g->alliance[i].name);
g->alliance[i].guild_id=0;
mapif->guild_alliance(g->guild_id,guild_id,account_id1,account_id2,flag,g->name,name);
g->save_flag |= GS_ALLIANCE;
- return 0;
+ return true;
}
// Alliance modification
-int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_id1, int account_id2, int flag)
+static bool inter_guild_change_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag)
{
// Could speed up
struct guild *g[2] = { NULL };
@@ -1734,10 +1435,10 @@ int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_
g[1] = inter_guild->fromsql(guild_id2);
if(g[0] && g[1]==NULL && (flag & GUILD_ALLIANCE_REMOVE)) //Requested to remove an alliance with a not found guild.
- return mapif->parse_GuildDeleteAlliance(g[0], guild_id2, account_id1, account_id2, flag); //Try to do a manual removal of said guild.
+ return inter_guild->remove_alliance(g[0], guild_id2, account_id1, account_id2, flag); //Try to do a manual removal of said guild.
if(g[0]==NULL || g[1]==NULL)
- return 0;
+ return false;
if( flag&GUILD_ALLIANCE_REMOVE ) {
// Remove alliance/opposition, in case of alliance, remove on both side
@@ -1766,11 +1467,11 @@ int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_
// Mark the two guild to be saved
g[0]->save_flag |= GS_ALLIANCE;
g[1]->save_flag |= GS_ALLIANCE;
- return 0;
+ return true;
}
// Change guild message
-int mapif_parse_GuildNotice(int fd, int guild_id, const char *mes1, const char *mes2)
+static bool inter_guild_update_notice(int guild_id, const char *mes1, const char *mes2)
{
struct guild *g;
@@ -1778,22 +1479,23 @@ int mapif_parse_GuildNotice(int fd, int guild_id, const char *mes1, const char *
nullpo_ret(mes2);
g = inter_guild->fromsql(guild_id);
if(g==NULL)
- return 0;
+ return false;
memcpy(g->mes1,mes1,MAX_GUILDMES1);
memcpy(g->mes2,mes2,MAX_GUILDMES2);
g->save_flag |= GS_MES; //Change mes of guild
- return mapif->guild_notice(g);
+ mapif->guild_notice(g);
+ return true;
}
-int mapif_parse_GuildEmblem(int fd, int len, int guild_id, int dummy, const char *data)
+static bool inter_guild_update_emblem(int len, int guild_id, const char *data)
{
struct guild * g;
nullpo_ret(data);
g = inter_guild->fromsql(guild_id);
if(g==NULL)
- return 0;
+ return false;
if (len > sizeof(g->emblem_data))
len = sizeof(g->emblem_data);
@@ -1802,21 +1504,17 @@ int mapif_parse_GuildEmblem(int fd, int len, int guild_id, int dummy, const char
g->emblem_len=len;
g->emblem_id++;
g->save_flag |= GS_EMBLEM; //Change guild
- return mapif->guild_emblem(g);
-}
-
-int mapif_parse_GuildCastleDataLoad(int fd, int len, const int *castle_ids)
-{
- return mapif->guild_castle_dataload(fd, len, castle_ids);
+ mapif->guild_emblem(g);
+ return true;
}
-int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
+static bool inter_guild_update_castle_data(int castle_id, int index, int value)
{
struct guild_castle *gc = inter_guild->castle_fromsql(castle_id);
if (gc == NULL) {
- ShowError("mapif->parse_GuildCastleDataSave: castle id=%d not found\n", castle_id);
- return 0;
+ ShowError("inter_guild->update_castle_data: castle id=%d not found\n", castle_id);
+ return false;
}
switch (index) {
@@ -1842,14 +1540,14 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
gc->guardian[index-10].visible = value;
break;
}
- ShowError("mapif->parse_GuildCastleDataSave: not found index=%d\n", index);
- return 0;
+ ShowError("inter_guild->update_castle_data: not found index=%d\n", index);
+ return false;
}
inter_guild->castle_tosql(gc);
- return 0;
+ return true;
}
-int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int len)
+static bool inter_guild_change_leader(int guild_id, const char *name, int len)
{
struct guild * g;
struct guild_member gm;
@@ -1884,7 +1582,8 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le
ShowInfo("int_guild: Guildmaster Changed to %s (Guild %d - %s)\n",g->master, guild_id, g->name);
g->save_flag |= (GS_BASIC|GS_MEMBER); //Save main data and member data.
- return mapif->guild_master_changed(g, g->member[0].account_id, g->member[0].char_id);
+ mapif->guild_master_changed(g, g->member[0].account_id, g->member[0].char_id);
+ return true;
}
// Communication from the map server
@@ -1894,7 +1593,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le
// Must Return
// 1 : ok
// 0 : error
-int inter_guild_parse_frommap(int fd)
+static int inter_guild_parse_frommap(int fd)
{
RFIFOHEAD(fd);
switch(RFIFOW(fd,0)) {
@@ -1923,13 +1622,7 @@ int inter_guild_parse_frommap(int fd)
return 1;
}
-//Leave request from the server (for deleting character from guild)
-int inter_guild_leave(int guild_id, int account_id, int char_id)
-{
- return mapif->parse_GuildLeave(-1, guild_id, account_id, char_id, 0, "** Character Deleted **");
-}
-
-int inter_guild_broken(int guild_id)
+static int inter_guild_broken(int guild_id)
{
return mapif->guild_broken(guild_id, 0);
}
@@ -1962,6 +1655,20 @@ void inter_guild_defaults(void)
inter_guild->sex_changed = inter_guild_sex_changed;
inter_guild->charname_changed = inter_guild_charname_changed;
inter_guild->parse_frommap = inter_guild_parse_frommap;
- inter_guild->leave = inter_guild_leave;
inter_guild->broken = inter_guild_broken;
+ inter_guild->create = inter_guild_create;
+ inter_guild->add_member = inter_guild_add_member;
+ inter_guild->leave = inter_guild_leave;
+ inter_guild->update_member_info_short = inter_guild_update_member_info_short;
+ inter_guild->update_member_info = inter_guild_update_member_info;
+ inter_guild->disband = inter_guild_disband;
+ inter_guild->update_basic_info = inter_guild_update_basic_info;
+ inter_guild->update_position = inter_guild_update_position;
+ inter_guild->use_skill_point = inter_guild_use_skill_point;
+ inter_guild->remove_alliance = inter_guild_remove_alliance;
+ inter_guild->change_alliance = inter_guild_change_alliance;
+ inter_guild->update_notice = inter_guild_update_notice;
+ inter_guild->update_emblem = inter_guild_update_emblem;
+ inter_guild->update_castle_data = inter_guild_update_castle_data;
+ inter_guild->change_leader = inter_guild_change_leader;
}
diff --git a/src/char/int_guild.h b/src/char/int_guild.h
index 93bf6c699..33873edcd 100644
--- a/src/char/int_guild.h
+++ b/src/char/int_guild.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -68,8 +68,22 @@ struct inter_guild_interface {
int (*sex_changed) (int guild_id, int account_id, int char_id, short gender);
int (*charname_changed) (int guild_id, int account_id, int char_id, char *name);
int (*parse_frommap) (int fd);
- int (*leave) (int guild_id, int account_id, int char_id);
int (*broken) (int guild_id);
+ struct guild *(*create) (const char *name, const struct guild_member *master);
+ bool (*add_member) (int guild_id, const struct guild_member *member, int map_fd);
+ bool (*leave) (int guild_id, int account_id, int char_id, int flag, const char *mes, int map_fd);
+ bool (*update_member_info_short) (int guild_id, int account_id, int char_id, int online, int lv, int16 class);
+ bool (*update_member_info) (int guild_id, int account_id, int char_id, int type, const char *data, int len);
+ bool (*disband) (int guild_id);
+ bool (*update_basic_info) (int guild_id, int type, const void *data, int len);
+ bool (*update_position) (int guild_id, int idx, const struct guild_position *p);
+ bool (*use_skill_point) (int guild_id, uint16 skill_id, int account_id, int max);
+ bool (*remove_alliance) (struct guild *g, int guild_id, int account_id1, int account_id2, int flag);
+ bool (*change_alliance) (int guild_id1, int guild_id2, int account_id1, int account_id2, int flag);
+ bool (*update_notice) (int guild_id, const char *mes1, const char *mes2);
+ bool (*update_emblem) (int len, int guild_id, const char *data);
+ bool (*update_castle_data) (int castle_id, int index, int value);
+ bool (*change_leader) (int guild_id, const char *name, int len);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_homun.c b/src/char/int_homun.c
index 04f4c8f21..5a1c9d23f 100644
--- a/src/char/int_homun.c
+++ b/src/char/int_homun.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -37,78 +37,18 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_homunculus_interface inter_homunculus_s;
+static struct inter_homunculus_interface inter_homunculus_s;
struct inter_homunculus_interface *inter_homunculus;
-int inter_homunculus_sql_init(void)
+static int inter_homunculus_sql_init(void)
{
return 0;
}
-void inter_homunculus_sql_final(void)
+static void inter_homunculus_sql_final(void)
{
return;
}
-void mapif_homunculus_created(int fd, int account_id, const struct s_homunculus *sh, unsigned char flag)
-{
- nullpo_retv(sh);
- WFIFOHEAD(fd, sizeof(struct s_homunculus)+9);
- WFIFOW(fd,0) = 0x3890;
- WFIFOW(fd,2) = sizeof(struct s_homunculus)+9;
- WFIFOL(fd,4) = account_id;
- WFIFOB(fd,8)= flag;
- memcpy(WFIFOP(fd,9),sh,sizeof(struct s_homunculus));
- WFIFOSET(fd, WFIFOW(fd,2));
-}
-
-void mapif_homunculus_deleted(int fd, int flag)
-{
- WFIFOHEAD(fd, 3);
- WFIFOW(fd, 0) = 0x3893;
- WFIFOB(fd,2) = flag; //Flag 1 = success
- WFIFOSET(fd, 3);
-}
-
-void mapif_homunculus_loaded(int fd, int account_id, struct s_homunculus *hd)
-{
- WFIFOHEAD(fd, sizeof(struct s_homunculus)+9);
- WFIFOW(fd,0) = 0x3891;
- WFIFOW(fd,2) = sizeof(struct s_homunculus)+9;
- WFIFOL(fd,4) = account_id;
- if( hd != NULL )
- {
- WFIFOB(fd,8) = 1; // success
- memcpy(WFIFOP(fd,9), hd, sizeof(struct s_homunculus));
- }
- else
- {
- WFIFOB(fd,8) = 0; // not found.
- memset(WFIFOP(fd,9), 0, sizeof(struct s_homunculus));
- }
- WFIFOSET(fd, sizeof(struct s_homunculus)+9);
-}
-
-void mapif_homunculus_saved(int fd, int account_id, bool flag)
-{
- WFIFOHEAD(fd, 7);
- WFIFOW(fd,0) = 0x3892;
- WFIFOL(fd,2) = account_id;
- WFIFOB(fd,6) = flag; // 1:success, 0:failure
- WFIFOSET(fd, 7);
-}
-
-void mapif_homunculus_renamed(int fd, int account_id, int char_id, unsigned char flag, const char *name)
-{
- nullpo_retv(name);
- WFIFOHEAD(fd, NAME_LENGTH+12);
- WFIFOW(fd, 0) = 0x3894;
- WFIFOL(fd, 2) = account_id;
- WFIFOL(fd, 6) = char_id;
- WFIFOB(fd,10) = flag;
- safestrncpy(WFIFOP(fd,11), name, NAME_LENGTH);
- WFIFOSET(fd, NAME_LENGTH+12);
-}
-
/**
* Creates a new homunculus with the given data.
*
@@ -119,7 +59,7 @@ void mapif_homunculus_renamed(int fd, int account_id, int char_id, unsigned char
* @param[in,out] hd The new homunculus' data.
* @retval false in case of errors.
*/
-bool mapif_homunculus_create(struct s_homunculus *hd)
+static bool inter_homunculus_create(struct s_homunculus *hd)
{
char esc_name[NAME_LENGTH*2+1];
@@ -129,10 +69,10 @@ bool mapif_homunculus_create(struct s_homunculus *hd)
SQL->EscapeStringLen(inter->sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH));
if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` "
- "(`char_id`, `class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) "
- "VALUES ('%d', '%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
+ "(`char_id`, `class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`, `autofeed`) "
+ "VALUES ('%d', '%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
- hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize)) {
+ hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->autofeed)) {
Sql_ShowDebug(inter->sql_handle);
return false;
}
@@ -146,7 +86,7 @@ bool mapif_homunculus_create(struct s_homunculus *hd)
* @param hd The homunculus' data.
* @retval false in case of errors.
*/
-bool mapif_homunculus_save(const struct s_homunculus *hd)
+static bool inter_homunculus_save(const struct s_homunculus *hd)
{
bool flag = true;
char esc_name[NAME_LENGTH*2+1];
@@ -156,9 +96,9 @@ bool mapif_homunculus_save(const struct s_homunculus *hd)
SQL->EscapeStringLen(inter->sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH));
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'",
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d', `autofeed`='%d' WHERE `homun_id`='%d'",
homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
- hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id)) {
+ hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->autofeed, hd->hom_id)) {
Sql_ShowDebug(inter->sql_handle);
flag = false;
} else {
@@ -171,9 +111,9 @@ bool mapif_homunculus_save(const struct s_homunculus *hd)
} else {
for (i = 0; i < MAX_HOMUNSKILL; ++i) {
if (hd->hskill[i].id > 0 && hd->hskill[i].lv != 0) {
- SQL->StmtBindParam(stmt, 0, SQLDT_USHORT, &hd->hskill[i].id, 0);
- SQL->StmtBindParam(stmt, 1, SQLDT_USHORT, &hd->hskill[i].lv, 0);
- if (SQL_ERROR == SQL->StmtExecute(stmt)) {
+ if (SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_USHORT, &hd->hskill[i].id, sizeof hd->hskill[i].id)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_UCHAR, &hd->hskill[i].lv, sizeof hd->hskill[i].lv)
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
SqlStmt_ShowDebug(stmt);
flag = false;
break;
@@ -188,7 +128,7 @@ bool mapif_homunculus_save(const struct s_homunculus *hd)
}
// Load an homunculus
-bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd)
+static bool inter_homunculus_load(int homun_id, struct s_homunculus *hd)
{
char* data;
size_t len;
@@ -196,7 +136,7 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd)
nullpo_ret(hd);
memset(hd, 0, sizeof(*hd));
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%d'", homunculus_db, homun_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize`, `autofeed` FROM `%s` WHERE `homun_id`='%d'", homunculus_db, homun_id))
{
Sql_ShowDebug(inter->sql_handle);
return false;
@@ -236,6 +176,7 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd)
SQL->GetData(inter->sql_handle, 19, &data, NULL); hd->skillpts = atoi(data);
SQL->GetData(inter->sql_handle, 20, &data, NULL); hd->rename_flag = atoi(data);
SQL->GetData(inter->sql_handle, 21, &data, NULL); hd->vaporize = atoi(data);
+ SQL->GetData(inter->sql_handle, 22, &data, NULL); hd->autofeed = atoi(data);
SQL->FreeResult(inter->sql_handle);
hd->intimacy = cap_value(hd->intimacy, 0, 100000);
@@ -268,7 +209,7 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd)
return true;
}
-bool mapif_homunculus_delete(int homun_id)
+static bool inter_homunculus_delete(int homun_id)
{
if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%d'", homunculus_db, homun_id)
|| SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%d'", skill_homunculus_db, homun_id)
@@ -279,7 +220,7 @@ bool mapif_homunculus_delete(int homun_id)
return true;
}
-bool mapif_homunculus_rename(const char *name)
+static bool inter_homunculus_rename(const char *name)
{
int i;
@@ -301,47 +242,10 @@ bool mapif_homunculus_rename(const char *name)
return true;
}
-
-void mapif_parse_homunculus_create(int fd, int len, int account_id, const struct s_homunculus *phd)
-{
- struct s_homunculus shd;
- bool result;
-
- memcpy(&shd, phd, sizeof(shd));
-
- result = mapif->homunculus_create(&shd);
- mapif->homunculus_created(fd, account_id, &shd, result);
-}
-
-void mapif_parse_homunculus_delete(int fd, int homun_id)
-{
- bool result = mapif->homunculus_delete(homun_id);
- mapif->homunculus_deleted(fd, result);
-}
-
-void mapif_parse_homunculus_load(int fd, int account_id, int homun_id)
-{
- struct s_homunculus hd;
- bool result = mapif->homunculus_load(homun_id, &hd);
- mapif->homunculus_loaded(fd, account_id, ( result ? &hd : NULL ));
-}
-
-void mapif_parse_homunculus_save(int fd, int len, int account_id, const struct s_homunculus *phd)
-{
- bool result = mapif->homunculus_save(phd);
- mapif->homunculus_saved(fd, account_id, result);
-}
-
-void mapif_parse_homunculus_rename(int fd, int account_id, int char_id, const char *name)
-{
- bool result = mapif->homunculus_rename(name);
- mapif->homunculus_renamed(fd, account_id, char_id, result, name);
-}
-
/*==========================================
* Inter Packets
*------------------------------------------*/
-int inter_homunculus_parse_frommap(int fd)
+static int inter_homunculus_parse_frommap(int fd)
{
unsigned short cmd = RFIFOW(fd,0);
@@ -364,4 +268,10 @@ void inter_homunculus_defaults(void)
inter_homunculus->sql_init = inter_homunculus_sql_init;
inter_homunculus->sql_final = inter_homunculus_sql_final;
inter_homunculus->parse_frommap = inter_homunculus_parse_frommap;
+
+ inter_homunculus->create = inter_homunculus_create;
+ inter_homunculus->save = inter_homunculus_save;
+ inter_homunculus->load = inter_homunculus_load;
+ inter_homunculus->delete = inter_homunculus_delete;
+ inter_homunculus->rename = inter_homunculus_rename;
}
diff --git a/src/char/int_homun.h b/src/char/int_homun.h
index 7ea7331f2..8eba66963 100644
--- a/src/char/int_homun.h
+++ b/src/char/int_homun.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#define CHAR_INT_HOMUN_H
#include "common/hercules.h"
+#include "common/mmo.h"
/**
* inter_homunculus interface
@@ -30,6 +31,12 @@ struct inter_homunculus_interface {
int (*sql_init) (void);
void (*sql_final) (void);
int (*parse_frommap) (int fd);
+
+ bool (*create) (struct s_homunculus *hd);
+ bool (*save) (const struct s_homunculus *hd);
+ bool (*load) (int homun_id, struct s_homunculus* hd);
+ bool (*delete) (int homun_id);
+ bool (*rename) (const char *name);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_mail.c b/src/char/int_mail.c
index 10f905a0d..e0625fcab 100644
--- a/src/char/int_mail.c
+++ b/src/char/int_mail.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -37,10 +37,10 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_mail_interface inter_mail_s;
+static struct inter_mail_interface inter_mail_s;
struct inter_mail_interface *inter_mail;
-static int inter_mail_fromsql(int char_id, struct mail_data* md)
+static int inter_mail_fromsql(int char_id, struct mail_data *md)
{
int i, j;
struct mail_message *msg;
@@ -57,6 +57,8 @@ static int inter_mail_fromsql(int char_id, struct mail_data* md)
"`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`,`unique_id`");
for (i = 0; i < MAX_SLOTS; i++)
StrBuf->Printf(&buf, ",`card%d`", i);
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
// I keep the `status` < 3 just in case someone forget to apply the sqlfix
StrBuf->Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' AND `status` < 3 ORDER BY `id` LIMIT %d",
@@ -90,12 +92,18 @@ static int inter_mail_fromsql(int char_id, struct mail_data* md)
SQL->GetData(inter->sql_handle,15, &data, NULL); item->unique_id = strtoull(data, NULL, 10);
item->expire_time = 0;
item->bound = 0;
-
- for (j = 0; j < MAX_SLOTS; j++)
- {
+ /* Card Slots */
+ for (j = 0; j < MAX_SLOTS; j++) {
SQL->GetData(inter->sql_handle, 16 + j, &data, NULL);
item->card[j] = atoi(data);
}
+ /* Item Options */
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++) {
+ SQL->GetData(inter->sql_handle, 16 + MAX_SLOTS + j * 2, &data, NULL);
+ item->option[j].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 17 + MAX_SLOTS + j * 2, &data, NULL);
+ item->option[j].value = atoi(data);
+ }
}
md->full = ( SQL->NumRows(inter->sql_handle) > MAIL_MAX_INBOX );
@@ -126,7 +134,7 @@ static int inter_mail_fromsql(int char_id, struct mail_data* md)
/// Stores a single message in the database.
/// Returns the message's ID if successful (or 0 if it fails).
-int inter_mail_savemessage(struct mail_message* msg)
+static int inter_mail_savemessage(struct mail_message *msg)
{
StringBuf buf;
struct SqlStmt *stmt;
@@ -138,25 +146,30 @@ int inter_mail_savemessage(struct mail_message* msg)
StrBuf->Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `status`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`, `unique_id`", mail_db);
for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ", `card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j);
StrBuf->Printf(&buf, ") VALUES (?, '%d', ?, '%d', ?, ?, '%lu', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%"PRIu64"'",
msg->send_id, msg->dest_id, (unsigned long)msg->timestamp, msg->status, msg->zeny, msg->item.amount, msg->item.nameid, msg->item.refine, msg->item.attribute, msg->item.identify, msg->item.unique_id);
for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ", '%d'", msg->item.card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ", '%d', '%d'", msg->item.option[j].index, msg->item.option[j].value);
StrBuf->AppendStr(&buf, ")");
// prepare and execute query
stmt = SQL->StmtMalloc(inter->sql_handle);
- if( SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
+ if (SQL_SUCCESS != SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, msg->send_name, strnlen(msg->send_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 2, SQLDT_STRING, msg->title, strnlen(msg->title, MAIL_TITLE_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 3, SQLDT_STRING, msg->body, strnlen(msg->body, MAIL_BODY_LENGTH))
- || SQL_SUCCESS != SQL->StmtExecute(stmt) )
+ || SQL_SUCCESS != SQL->StmtExecute(stmt))
{
SqlStmt_ShowDebug(stmt);
msg->id = 0;
- } else
+ } else {
msg->id = (int)SQL->StmtLastInsertId(stmt);
+ }
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
@@ -166,7 +179,7 @@ int inter_mail_savemessage(struct mail_message* msg)
/// Retrieves a single message from the database.
/// Returns true if the operation succeeds (or false if it fails).
-static bool inter_mail_loadmessage(int mail_id, struct mail_message* msg)
+static bool inter_mail_loadmessage(int mail_id, struct mail_message *msg)
{
int j;
StringBuf buf;
@@ -176,8 +189,10 @@ static bool inter_mail_loadmessage(int mail_id, struct mail_message* msg)
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`,"
"`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`,`unique_id`");
- for( j = 0; j < MAX_SLOTS; j++ )
+ for (j = 0; j < MAX_SLOTS; j++)
StrBuf->Printf(&buf, ",`card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++)
+ StrBuf->Printf(&buf, ",`opt_idx%d`,`opt_val%d`", j, j);
StrBuf->Printf(&buf, " FROM `%s` WHERE `id` = '%d'", mail_db, mail_id);
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))
@@ -207,12 +222,18 @@ static bool inter_mail_loadmessage(int mail_id, struct mail_message* msg)
SQL->GetData(inter->sql_handle,15, &data, NULL); msg->item.unique_id = strtoull(data, NULL, 10);
msg->item.expire_time = 0;
msg->item.bound = 0;
-
- for( j = 0; j < MAX_SLOTS; j++ )
- {
+ /* Card Slots */
+ for (j = 0; j < MAX_SLOTS; j++) {
SQL->GetData(inter->sql_handle,16 + j, &data, NULL);
msg->item.card[j] = atoi(data);
}
+ /* Item Options */
+ for (j = 0 ; j < MAX_ITEM_OPTIONS; j++) {
+ SQL->GetData(inter->sql_handle, 16 + MAX_SLOTS + j * 2, &data, NULL);
+ msg->item.option[j].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 17 + MAX_SLOTS + j * 2, &data, NULL);
+ msg->item.option[j].value = atoi(data);
+ }
}
StrBuf->Destroy(&buf);
@@ -221,40 +242,16 @@ static bool inter_mail_loadmessage(int mail_id, struct mail_message* msg)
return true;
}
-void mapif_mail_sendinbox(int fd, int char_id, unsigned char flag, struct mail_data *md)
-{
- nullpo_retv(md);
- //FIXME: dumping the whole structure like this is unsafe [ultramage]
- WFIFOHEAD(fd, sizeof(struct mail_data) + 9);
- 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),md,sizeof(struct mail_data));
- WFIFOSET(fd,WFIFOW(fd,2));
-}
-
-/*==========================================
- * Client Inbox Request
- *------------------------------------------*/
-void mapif_parse_mail_requestinbox(int fd)
-{
- int char_id = RFIFOL(fd,2);
- unsigned char flag = RFIFOB(fd,6);
- struct mail_data md;
- memset(&md, 0, sizeof(md));
- inter_mail->fromsql(char_id, &md);
- mapif->mail_sendinbox(fd, char_id, flag, &md);
-}
-
/*==========================================
* Mark mail as 'Read'
*------------------------------------------*/
-void mapif_parse_mail_read(int fd)
+static bool inter_mail_mark_read(int mail_id)
{
- int mail_id = RFIFOL(fd,2);
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_READ, mail_id) )
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_READ, mail_id)) {
Sql_ShowDebug(inter->sql_handle);
+ return false;
+ }
+ return true;
}
/*==========================================
@@ -269,6 +266,8 @@ static bool inter_mail_DeleteAttach(int mail_id)
StrBuf->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++)
StrBuf->Printf(&buf, ", `card%d` = '0'", i);
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++)
+ StrBuf->Printf(&buf, ", `opt_idx%d` = '0', `opt_val%d` = '0'", i, i);
StrBuf->Printf(&buf, " WHERE `id` = '%d'", mail_id);
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
@@ -282,194 +281,103 @@ static bool inter_mail_DeleteAttach(int mail_id)
return true;
}
-void mapif_mail_sendattach(int fd, int char_id, struct mail_message *msg)
+static bool inter_mail_get_attachment(int char_id, int mail_id, struct mail_message *msg)
{
- nullpo_retv(msg);
- 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) = (msg->zeny > 0)?msg->zeny:0;
- memcpy(WFIFOP(fd,12), &msg->item, sizeof(struct item));
- WFIFOSET(fd,WFIFOW(fd,2));
-}
-
-void mapif_mail_getattach(int fd, int char_id, int mail_id)
-{
- struct mail_message msg;
- memset(&msg, 0, sizeof(msg));
-
- if( !inter_mail->loadmessage(mail_id, &msg) )
- return;
-
- if( msg.dest_id != char_id )
- return;
+ nullpo_retr(false, msg);
- if( msg.status != MAIL_READ )
- return;
+ if (!inter_mail->loadmessage(mail_id, msg))
+ return false;
- if( (msg.item.nameid < 1 || msg.item.amount < 1) && msg.zeny < 1 )
- return; // No Attachment
+ if (msg->dest_id != char_id)
+ return false;
- if( !inter_mail->DeleteAttach(mail_id) )
- return;
+ if (msg->status != MAIL_READ)
+ return false;
- mapif->mail_sendattach(fd, char_id, &msg);
-}
+ if ((msg->item.nameid < 1 || msg->item.amount < 1) && msg->zeny < 1)
+ return false; // No Attachment
-void mapif_parse_mail_getattach(int fd)
-{
- mapif->mail_getattach(fd, RFIFOL(fd,2), RFIFOL(fd,6));
-}
+ if (!inter_mail->DeleteAttach(mail_id))
+ return false;
-/*==========================================
- * Delete Mail
- *------------------------------------------*/
-void mapif_mail_delete(int fd, int char_id, int mail_id, bool failed)
-{
- WFIFOHEAD(fd,11);
- WFIFOW(fd,0) = 0x384b;
- WFIFOL(fd,2) = char_id;
- WFIFOL(fd,6) = mail_id;
- WFIFOB(fd,10) = failed;
- WFIFOSET(fd,11);
+ return true;
}
-void mapif_parse_mail_delete(int fd)
+static bool inter_mail_delete(int char_id, int mail_id)
{
- int char_id = RFIFOL(fd,2);
- int mail_id = RFIFOL(fd,6);
- bool failed = false;
- if ( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) )
- {
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id)) {
Sql_ShowDebug(inter->sql_handle);
- failed = true;
+ return false;
}
- mapif->mail_delete(fd, char_id, mail_id, failed);
+ return true;
}
-/*==========================================
- * Report New Mail to Map Server
- *------------------------------------------*/
-void mapif_mail_new(struct mail_message *msg)
+static bool inter_mail_return_message(int char_id, int mail_id, int *new_mail)
{
- unsigned char buf[74];
-
- if( !msg || !msg->id )
- return;
-
- WBUFW(buf,0) = 0x3849;
- WBUFL(buf,2) = msg->dest_id;
- WBUFL(buf,6) = msg->id;
- memcpy(WBUFP(buf,10), msg->send_name, NAME_LENGTH);
- memcpy(WBUFP(buf,34), msg->title, MAIL_TITLE_LENGTH);
- mapif->sendall(buf, 74);
-}
+ struct mail_message msg;
+ nullpo_retr(false, new_mail);
-/*==========================================
- * Return Mail
- *------------------------------------------*/
-void mapif_mail_return(int fd, int char_id, int mail_id, int new_mail)
-{
- WFIFOHEAD(fd,11);
- WFIFOW(fd,0) = 0x384c;
- WFIFOL(fd,2) = char_id;
- WFIFOL(fd,6) = mail_id;
- WFIFOB(fd,10) = (new_mail == 0);
- WFIFOSET(fd,11);
-}
+ if (!inter_mail->loadmessage(mail_id, &msg))
+ return false;
-void mapif_parse_mail_return(int fd)
-{
- int char_id = RFIFOL(fd,2);
- int mail_id = RFIFOL(fd,6);
- struct mail_message msg;
- int new_mail = 0;
+ if (msg.dest_id != char_id)
+ return false;
- if( inter_mail->loadmessage(mail_id, &msg) )
- {
- if( msg.dest_id != char_id)
- return;
- else if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) )
- Sql_ShowDebug(inter->sql_handle);
- else
- {
- char temp_[MAIL_TITLE_LENGTH];
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id)) {
+ Sql_ShowDebug(inter->sql_handle);
+ } else {
+ char temp_[MAIL_TITLE_LENGTH];
- // swap sender and receiver
- 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);
+ // swap sender and receiver
+ 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);
- // set reply message title
- snprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg.title);
- safestrncpy(msg.title, temp_, MAIL_TITLE_LENGTH);
+ // set reply message title
+ safesnprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg.title);
+ safestrncpy(msg.title, temp_, MAIL_TITLE_LENGTH);
- msg.status = MAIL_NEW;
- msg.timestamp = time(NULL);
+ msg.status = MAIL_NEW;
+ msg.timestamp = time(NULL);
- new_mail = inter_mail->savemessage(&msg);
- mapif->mail_new(&msg);
- }
+ *new_mail = inter_mail->savemessage(&msg);
+ mapif->mail_new(&msg);
}
- mapif->mail_return(fd, char_id, mail_id, new_mail);
-}
+ return true;
-/*==========================================
- * Send Mail
- *------------------------------------------*/
-void mapif_mail_send(int fd, struct mail_message* msg)
-{
- int len = sizeof(struct mail_message) + 4;
-
- nullpo_retv(msg);
- WFIFOHEAD(fd,len);
- WFIFOW(fd,0) = 0x384d;
- WFIFOW(fd,2) = len;
- memcpy(WFIFOP(fd,4), msg, sizeof(struct mail_message));
- WFIFOSET(fd,len);
}
-void mapif_parse_mail_send(int fd)
+static bool inter_mail_send(int account_id, struct mail_message *msg)
{
- struct mail_message msg;
char esc_name[NAME_LENGTH*2+1];
- int account_id = 0;
-
- if(RFIFOW(fd,2) != 8 + sizeof(struct mail_message))
- return;
- account_id = RFIFOL(fd,4);
- memcpy(&msg, RFIFOP(fd,8), sizeof(struct mail_message));
+ nullpo_retr(false, msg);
// Try to find the Dest Char by Name
- SQL->EscapeStringLen(inter->sql_handle, esc_name, msg.dest_name, strnlen(msg.dest_name, NAME_LENGTH));
- if ( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
+ SQL->EscapeStringLen(inter->sql_handle, esc_name, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH));
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name)) {
Sql_ShowDebug(inter->sql_handle);
- else
- if ( SQL_SUCCESS == SQL->NextRow(inter->sql_handle) )
- {
+ } else if (SQL_SUCCESS == SQL->NextRow(inter->sql_handle)) {
char *data;
SQL->GetData(inter->sql_handle, 0, &data, NULL);
- if (atoi(data) != account_id)
- { // Cannot send mail to char in the same account
+ if (atoi(data) != account_id) {
+ // Cannot send mail to char in the same account
SQL->GetData(inter->sql_handle, 1, &data, NULL);
- msg.dest_id = atoi(data);
+ msg->dest_id = atoi(data);
}
}
SQL->FreeResult(inter->sql_handle);
- msg.status = MAIL_NEW;
+ msg->status = MAIL_NEW;
- if( msg.dest_id > 0 )
- msg.id = inter_mail->savemessage(&msg);
+ if (msg->dest_id > 0)
+ msg->id = inter_mail->savemessage(msg);
- mapif->mail_send(fd, &msg); // notify sender
- mapif->mail_new(&msg); // notify recipient
+ return true;
}
-void inter_mail_sendmail(int send_id, const char* send_name, int dest_id, const char* dest_name, const char* title, const char* body, int zeny, struct item *item)
+static void inter_mail_sendmail(int send_id, const char* send_name, int dest_id, const char *dest_name, const char *title, const char *body, int zeny, struct item *item)
{
struct mail_message msg;
nullpo_retv(send_name);
@@ -497,7 +405,7 @@ void inter_mail_sendmail(int send_id, const char* send_name, int dest_id, const
/*==========================================
* Packets From Map Server
*------------------------------------------*/
-int inter_mail_parse_frommap(int fd)
+static int inter_mail_parse_frommap(int fd)
{
switch(RFIFOW(fd,0))
{
@@ -513,12 +421,12 @@ int inter_mail_parse_frommap(int fd)
return 1;
}
-int inter_mail_sql_init(void)
+static int inter_mail_sql_init(void)
{
return 1;
}
-void inter_mail_sql_final(void)
+static void inter_mail_sql_final(void)
{
return;
}
@@ -535,4 +443,9 @@ void inter_mail_defaults(void)
inter_mail->sql_final = inter_mail_sql_final;
inter_mail->fromsql = inter_mail_fromsql;
inter_mail->loadmessage = inter_mail_loadmessage;
+ inter_mail->mark_read = inter_mail_mark_read;
+ inter_mail->get_attachment = inter_mail_get_attachment;
+ inter_mail->delete = inter_mail_delete;
+ inter_mail->return_message = inter_mail_return_message;
+ inter_mail->send = inter_mail_send;
}
diff --git a/src/char/int_mail.h b/src/char/int_mail.h
index cb72db504..95934d0a1 100644
--- a/src/char/int_mail.h
+++ b/src/char/int_mail.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -39,6 +39,11 @@ struct inter_mail_interface {
bool (*loadmessage) (int mail_id, struct mail_message* msg);
bool (*DeleteAttach) (int mail_id);
void (*sendmail) (int send_id, const char* send_name, int dest_id, const char* dest_name, const char* title, const char* body, int zeny, struct item *item);
+ bool (*mark_read) (int mail_id);
+ bool (*get_attachment) (int char_id, int mail_id, struct mail_message *msg);
+ bool (*delete) (int char_id, int mail_id);
+ bool (*return_message) (int char_id, int mail_id, int *new_mail);
+ bool (*send) (int account_id, struct mail_message *msg);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_mercenary.c b/src/char/int_mercenary.c
index f96e45a50..21bfb5538 100644
--- a/src/char/int_mercenary.c
+++ b/src/char/int_mercenary.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -38,10 +38,10 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_mercenary_interface inter_mercenary_s;
+static struct inter_mercenary_interface inter_mercenary_s;
struct inter_mercenary_interface *inter_mercenary;
-bool inter_mercenary_owner_fromsql(int char_id, struct mmo_charstatus *status)
+static bool inter_mercenary_owner_fromsql(int char_id, struct mmo_charstatus *status)
{
char* data;
@@ -70,7 +70,7 @@ bool inter_mercenary_owner_fromsql(int char_id, struct mmo_charstatus *status)
return true;
}
-bool inter_mercenary_owner_tosql(int char_id, struct mmo_charstatus *status)
+static bool inter_mercenary_owner_tosql(int char_id, struct mmo_charstatus *status)
{
nullpo_ret(status);
if( SQL_ERROR == SQL->Query(inter->sql_handle, "REPLACE INTO `%s` (`char_id`, `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith`) VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
@@ -83,7 +83,7 @@ bool inter_mercenary_owner_tosql(int char_id, struct mmo_charstatus *status)
return true;
}
-bool inter_mercenary_owner_delete(int char_id)
+static bool inter_mercenary_owner_delete(int char_id)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", mercenary_owner_db, char_id) )
Sql_ShowDebug(inter->sql_handle);
@@ -104,7 +104,7 @@ bool inter_mercenary_owner_delete(int char_id)
* @param[in,out] merc The new mercenary's data.
* @retval false in case of errors.
*/
-bool mapif_mercenary_create(struct s_mercenary *merc)
+static bool inter_mercenary_create(struct s_mercenary *merc)
{
nullpo_retr(false, merc);
Assert_retr(false, merc->mercenary_id == 0);
@@ -126,7 +126,7 @@ bool mapif_mercenary_create(struct s_mercenary *merc)
* @param merc The mercenary's data.
* @retval false in case of errors.
*/
-bool mapif_mercenary_save(const struct s_mercenary *merc)
+static bool inter_mercenary_save(const struct s_mercenary *merc)
{
nullpo_retr(false, merc);
Assert_retr(false, merc->mercenary_id > 0);
@@ -141,7 +141,7 @@ bool mapif_mercenary_save(const struct s_mercenary *merc)
return true;
}
-bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc)
+static bool inter_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc)
{
char* data;
@@ -174,7 +174,7 @@ bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc)
return true;
}
-bool mapif_mercenary_delete(int merc_id)
+static bool inter_mercenary_delete(int merc_id)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mer_id` = '%d'", mercenary_db, merc_id) )
{
@@ -185,70 +185,12 @@ bool mapif_mercenary_delete(int merc_id)
return true;
}
-void mapif_mercenary_send(int fd, struct s_mercenary *merc, unsigned char flag)
-{
- int size = sizeof(struct s_mercenary) + 5;
-
- nullpo_retv(merc);
- WFIFOHEAD(fd,size);
- WFIFOW(fd,0) = 0x3870;
- WFIFOW(fd,2) = size;
- WFIFOB(fd,4) = flag;
- memcpy(WFIFOP(fd,5),merc,sizeof(struct s_mercenary));
- WFIFOSET(fd,size);
-}
-
-void mapif_parse_mercenary_create(int fd, const struct s_mercenary *merc)
-{
- struct s_mercenary merc_;
- bool result;
-
- memcpy(&merc_, merc, sizeof(merc_));
-
- result = mapif->mercenary_create(&merc_);
- mapif->mercenary_send(fd, &merc_, result);
-}
-
-void mapif_parse_mercenary_load(int fd, int merc_id, int char_id)
-{
- struct s_mercenary merc;
- bool result = mapif->mercenary_load(merc_id, char_id, &merc);
- mapif->mercenary_send(fd, &merc, result);
-}
-
-void mapif_mercenary_deleted(int fd, unsigned char flag)
-{
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x3871;
- WFIFOB(fd,2) = flag;
- WFIFOSET(fd,3);
-}
-
-void mapif_parse_mercenary_delete(int fd, int merc_id)
-{
- bool result = mapif->mercenary_delete(merc_id);
- mapif->mercenary_deleted(fd, result);
-}
-
-void mapif_mercenary_saved(int fd, unsigned char flag)
-{
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x3872;
- WFIFOB(fd,2) = flag;
- WFIFOSET(fd,3);
-}
-
-void mapif_parse_mercenary_save(int fd, struct s_mercenary* merc)
-{
- bool result = mapif->mercenary_save(merc);
- mapif->mercenary_saved(fd, result);
-}
-
-int inter_mercenary_sql_init(void)
+static int inter_mercenary_sql_init(void)
{
return 0;
}
-void inter_mercenary_sql_final(void)
+
+static void inter_mercenary_sql_final(void)
{
return;
}
@@ -256,7 +198,7 @@ void inter_mercenary_sql_final(void)
/*==========================================
* Inter Packets
*------------------------------------------*/
-int inter_mercenary_parse_frommap(int fd)
+static int inter_mercenary_parse_frommap(int fd)
{
unsigned short cmd = RFIFOW(fd,0);
@@ -282,4 +224,9 @@ void inter_mercenary_defaults(void)
inter_mercenary->sql_init = inter_mercenary_sql_init;
inter_mercenary->sql_final = inter_mercenary_sql_final;
inter_mercenary->parse_frommap = inter_mercenary_parse_frommap;
+
+ inter_mercenary->create = inter_mercenary_create;
+ inter_mercenary->load = inter_mercenary_load;
+ inter_mercenary->save = inter_mercenary_save;
+ inter_mercenary->delete = inter_mercenary_delete;
}
diff --git a/src/char/int_mercenary.h b/src/char/int_mercenary.h
index 3b1623438..6291bfcf6 100644
--- a/src/char/int_mercenary.h
+++ b/src/char/int_mercenary.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#define CHAR_INT_MERCENARY_H
#include "common/hercules.h"
+#include "common/mmo.h"
struct mmo_charstatus;
@@ -35,6 +36,11 @@ struct inter_mercenary_interface {
int (*sql_init) (void);
void (*sql_final) (void);
int (*parse_frommap) (int fd);
+
+ bool (*create) (struct s_mercenary *merc);
+ bool (*save) (const struct s_mercenary *merc);
+ bool (*load) (int merc_id, int char_id, struct s_mercenary *merc);
+ bool (*delete) (int merc_id);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_party.c b/src/char/int_party.c
index 921bf6d9d..8ee03ecc5 100644
--- a/src/char/int_party.c
+++ b/src/char/int_party.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -39,11 +39,12 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_party_interface inter_party_s;
+static struct inter_party_interface inter_party_s;
struct inter_party_interface *inter_party;
//Updates party's level range and unsets even share if broken.
-static int inter_party_check_lv(struct party_data *p) {
+static int inter_party_check_lv(struct party_data *p)
+{
int i;
unsigned int lv;
nullpo_ret(p);
@@ -121,7 +122,7 @@ static void inter_party_calc_state(struct party_data *p)
}
// Save party to mysql
-int inter_party_tosql(struct party *p, int flag, int index)
+static int inter_party_tosql(struct party *p, int flag, int index)
{
// 'party' ('party_id','name','exp','item','leader_id','leader_char')
char esc_name[NAME_LENGTH*2+1];// escaped party name
@@ -196,7 +197,7 @@ int inter_party_tosql(struct party *p, int flag, int index)
}
// Read party from mysql
-struct party_data *inter_party_fromsql(int party_id)
+static struct party_data *inter_party_fromsql(int party_id)
{
int leader_id = 0;
int leader_char = 0;
@@ -268,7 +269,7 @@ struct party_data *inter_party_fromsql(int party_id)
return p;
}
-int inter_party_sql_init(void)
+static int inter_party_sql_init(void)
{
//memory alloc
inter_party->db = idb_alloc(DB_OPT_RELEASE_DATA);
@@ -287,7 +288,7 @@ int inter_party_sql_init(void)
return 0;
}
-void inter_party_sql_final(void)
+static void inter_party_sql_final(void)
{
inter_party->db->destroy(inter_party->db, NULL);
aFree(inter_party->pt);
@@ -295,7 +296,7 @@ void inter_party_sql_final(void)
}
// Search for the party according to its name
-struct party_data* inter_party_search_partyname(const char *const str)
+static struct party_data *inter_party_search_partyname(const char *const str)
{
char esc_name[NAME_LENGTH*2+1];
char* data;
@@ -314,14 +315,14 @@ struct party_data* inter_party_search_partyname(const char *const str)
}
// Returns whether this party can keep having exp share or not.
-int inter_party_check_exp_share(struct party_data *const p)
+static int inter_party_check_exp_share(struct party_data *const p)
{
nullpo_ret(p);
return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level);
}
// Is there any member in the party?
-int inter_party_check_empty(struct party_data *p)
+static int inter_party_check_empty(struct party_data *p)
{
int i;
if (p==NULL||p->party.party_id==0) return 1;
@@ -333,161 +334,16 @@ int inter_party_check_empty(struct party_data *p)
return 1;
}
-//-------------------------------------------------------------------
-// Communication to the map server
-
-
-// Create a party whether or not
-int mapif_party_created(int fd, int account_id, int char_id, struct party *p)
-{
- WFIFOHEAD(fd, 39);
- WFIFOW(fd,0)=0x3820;
- WFIFOL(fd,2)=account_id;
- WFIFOL(fd,6)=char_id;
- if(p!=NULL){
- WFIFOB(fd,10)=0;
- WFIFOL(fd,11)=p->party_id;
- memcpy(WFIFOP(fd,15),p->name,NAME_LENGTH);
- ShowInfo("int_party: Party created (%d - %s)\n",p->party_id,p->name);
- }else{
- WFIFOB(fd,10)=1;
- WFIFOL(fd,11)=0;
- memset(WFIFOP(fd,15),0,NAME_LENGTH);
- }
- WFIFOSET(fd,39);
-
- return 0;
-}
-
-//Party information not found
-void mapif_party_noinfo(int fd, int party_id, int char_id)
-{
- WFIFOHEAD(fd, 12);
- WFIFOW(fd,0) = 0x3821;
- WFIFOW(fd,2) = 12;
- WFIFOL(fd,4) = char_id;
- WFIFOL(fd,8) = party_id;
- WFIFOSET(fd,12);
- ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id);
-}
-
-//Digest party information
-void mapif_party_info(int fd, struct party* p, int char_id)
-{
- unsigned char buf[8 + sizeof(struct party)];
- nullpo_retv(p);
- WBUFW(buf,0) = 0x3821;
- WBUFW(buf,2) = 8 + sizeof(struct party);
- WBUFL(buf,4) = char_id;
- memcpy(WBUFP(buf,8), p, sizeof(struct party));
-
- if(fd<0)
- mapif->sendall(buf,WBUFW(buf,2));
- else
- mapif->send(fd,buf,WBUFW(buf,2));
-}
-
-//Whether or not additional party members
-int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag) {
- WFIFOHEAD(fd, 15);
- WFIFOW(fd,0) = 0x3822;
- WFIFOL(fd,2) = party_id;
- WFIFOL(fd,6) = account_id;
- WFIFOL(fd,10) = char_id;
- WFIFOB(fd,14) = flag;
- WFIFOSET(fd,15);
-
- return 0;
-}
-
-// Party setting change notification
-int mapif_party_optionchanged(int fd, struct party *p, int account_id, int flag)
-{
- unsigned char buf[16];
- nullpo_ret(p);
- WBUFW(buf,0)=0x3823;
- WBUFL(buf,2)=p->party_id;
- WBUFL(buf,6)=account_id;
- WBUFW(buf,10)=p->exp;
- WBUFW(buf,12)=p->item;
- WBUFB(buf,14)=flag;
- if(flag==0)
- mapif->sendall(buf,15);
- else
- mapif->send(fd,buf,15);
- return 0;
-}
-
-//Withdrawal notification party
-int mapif_party_withdraw(int party_id,int account_id, int char_id) {
- unsigned char buf[16];
-
- WBUFW(buf,0) = 0x3824;
- WBUFL(buf,2) = party_id;
- WBUFL(buf,6) = account_id;
- WBUFL(buf,10) = char_id;
- mapif->sendall(buf, 14);
- return 0;
-}
-
-//Party map update notification
-int mapif_party_membermoved(struct party *p, int idx)
-{
- unsigned char buf[20];
-
- nullpo_ret(p);
- Assert_ret(idx >= 0 && idx < MAX_PARTY);
- WBUFW(buf,0) = 0x3825;
- WBUFL(buf,2) = p->party_id;
- WBUFL(buf,6) = p->member[idx].account_id;
- WBUFL(buf,10) = p->member[idx].char_id;
- WBUFW(buf,14) = p->member[idx].map;
- WBUFB(buf,16) = p->member[idx].online;
- WBUFW(buf,17) = p->member[idx].lv;
- mapif->sendall(buf, 19);
- return 0;
-}
-
-//Dissolution party notification
-int mapif_party_broken(int party_id, int flag)
-{
- unsigned char buf[16];
- WBUFW(buf,0)=0x3826;
- WBUFL(buf,2)=party_id;
- WBUFB(buf,6)=flag;
- mapif->sendall(buf,7);
- //printf("int_party: broken %d\n",party_id);
- return 0;
-}
-
-//Remarks in the party
-int mapif_party_message(int party_id, int account_id, const char *mes, int len, int sfd)
-{
- unsigned char buf[512];
- nullpo_ret(mes);
- WBUFW(buf,0)=0x3827;
- WBUFW(buf,2)=len+12;
- WBUFL(buf,4)=party_id;
- WBUFL(buf,8)=account_id;
- memcpy(WBUFP(buf,12),mes,len);
- mapif->sendallwos(sfd, buf,len+12);
- return 0;
-}
-
-//-------------------------------------------------------------------
-// Communication from the map server
-
-
// Create Party
-int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const struct party_member *leader)
+static struct party_data *inter_party_create(const char *name, int item, int item2, const struct party_member *leader)
{
struct party_data *p;
int i;
nullpo_ret(name);
nullpo_ret(leader);
- if (!*name || (p = inter_party->search_partyname(name)) != NULL) {
- mapif->party_created(fd,leader->account_id,leader->char_id,NULL);
- return 0;
+
+ if (!*name || inter_party->search_partyname(name) != NULL) {
+ return NULL;
}
// Check Authorized letters/symbols in the name of the character
if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorized
@@ -497,18 +353,16 @@ int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const
char *newname = aStrndup(name, NAME_LENGTH-1);
normalize_name(newname,"\"");
trim(newname);
- mapif->parse_CreateParty(fd, newname, item, item2, leader);
+ p = inter_party->create(newname, item, item2, leader);
aFree(newname);
- return 0;
+ return p;
}
- mapif->party_created(fd,leader->account_id,leader->char_id,NULL);
- return 0;
+ return NULL;
}
} else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
for (i = 0; i < NAME_LENGTH && name[i]; i++)
if (strchr(char_name_letters, name[i]) != NULL) {
- mapif->party_created(fd,leader->account_id,leader->char_id,NULL);
- return 0;
+ return NULL;
}
}
@@ -523,34 +377,20 @@ int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const
p->party.member[0].online=1;
p->party.party_id=-1;//New party.
- if (inter_party->tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) {
- //Add party to db
- inter_party->calc_state(p);
- idb_put(inter_party->db, p->party.party_id, p);
- mapif->party_info(fd, &p->party, 0);
- mapif->party_created(fd,leader->account_id,leader->char_id,&p->party);
- } else { //Failed to create party.
+ if (!inter_party->tosql(&p->party, PS_CREATE | PS_ADDMEMBER, 0)) {
aFree(p);
- mapif->party_created(fd,leader->account_id,leader->char_id,NULL);
+ return NULL;
}
- return 0;
-}
-
-// Party information request
-void mapif_parse_PartyInfo(int fd, int party_id, int char_id)
-{
- struct party_data *p;
- p = inter_party->fromsql(party_id);
+ //Add party to db
+ inter_party->calc_state(p);
+ idb_put(inter_party->db, p->party.party_id, p);
- if (p)
- mapif->party_info(fd, &p->party, char_id);
- else
- mapif->party_noinfo(fd, party_id, char_id);
+ return p;
}
// Add a player to party request
-int mapif_parse_PartyAddMember(int fd, int party_id, const struct party_member *member)
+static bool inter_party_add_member(int party_id, const struct party_member *member)
{
struct party_data *p;
int i;
@@ -558,15 +398,13 @@ int mapif_parse_PartyAddMember(int fd, int party_id, const struct party_member *
nullpo_ret(member);
p = inter_party->fromsql(party_id);
if( p == NULL || p->size == MAX_PARTY ) {
- mapif->party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
- return 0;
+ return false;
}
ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == 0 );
- if( i == MAX_PARTY )
- {// Party full
- mapif->party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
- return 0;
+ if (i == MAX_PARTY) {
+ // Party full
+ return false;
}
memcpy(&p->party.member[i], member, sizeof(struct party_member));
@@ -582,21 +420,20 @@ int mapif_parse_PartyAddMember(int fd, int party_id, const struct party_member *
}
mapif->party_info(-1, &p->party, 0);
- mapif->party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
inter_party->tosql(&p->party, PS_ADDMEMBER, i);
- return 0;
+ return true;
}
//Party setting change request
-int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int item)
+static bool inter_party_change_option(int party_id, int account_id, int exp, int item, int map_fd)
{
struct party_data *p;
int flag = 0;
p = inter_party->fromsql(party_id);
if(!p)
- return 0;
+ return false;
p->party.exp=exp;
if( exp && !inter_party->check_exp_share(p) ){
@@ -604,13 +441,13 @@ int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int
p->party.exp=0;
}
p->party.item = item&0x3; //Filter out invalid values.
- mapif->party_optionchanged(fd,&p->party,account_id,flag);
+ mapif->party_optionchanged(map_fd, &p->party, account_id, flag);
inter_party->tosql(&p->party, PS_BASIC, 0);
- return 0;
+ return true;
}
//Request leave party
-int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
+static bool inter_party_leave(int party_id, int account_id, int char_id)
{
struct party_data *p;
int i,j;
@@ -620,7 +457,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
{// Party does not exists?
if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) )
Sql_ShowDebug(inter->sql_handle);
- return 0;
+ return false;
}
for (i = 0; i < MAX_PARTY; i++) {
@@ -630,10 +467,10 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
}
}
if (i >= MAX_PARTY)
- return 0; //Member not found?
+ return false; //Member not found?
mapif->party_withdraw(party_id, account_id, char_id);
-
+
j = p->party.member[i].lv;
if (p->party.member[i].online > 0)
p->party.count--;
@@ -648,23 +485,25 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
inter_party->tosql(&p->party, PS_DELMEMBER, i);
mapif->party_info(-1, &p->party, 0);
}
- return 0;
+ return true;
}
+
// When member goes to other map or levels up.
-int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv)
+static bool inter_party_change_map(int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv)
{
struct party_data *p;
int i;
p = inter_party->fromsql(party_id);
if (p == NULL)
- return 0;
+ return false;
for(i = 0; i < MAX_PARTY &&
(p->party.member[i].account_id != account_id ||
p->party.member[i].char_id != char_id); i++);
- if (i == MAX_PARTY) return 0;
+ if (i == MAX_PARTY)
+ return false;
if (p->party.member[i].online != online)
{
@@ -704,30 +543,24 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
p->party.member[i].map = map;
mapif->party_membermoved(&p->party, i);
}
- return 0;
+ return true;
}
//Request party dissolution
-int mapif_parse_BreakParty(int fd, int party_id)
+static bool inter_party_disband(int party_id)
{
struct party_data *p;
p = inter_party->fromsql(party_id);
if(!p)
- return 0;
+ return false;
inter_party->tosql(&p->party,PS_BREAK,0);
- mapif->party_broken(fd,party_id);
+ mapif->party_broken(party_id, 1);
return 0;
}
-//Party sending the message
-int mapif_parse_PartyMessage(int fd, int party_id, int account_id, const char *mes, int len)
-{
- return mapif->party_message(party_id,account_id,mes,len, fd);
-}
-
-int mapif_parse_PartyLeaderChange(int fd, int party_id, int account_id, int char_id)
+static bool inter_party_change_leader(int party_id, int account_id, int char_id)
{
struct party_data *p;
int i;
@@ -735,7 +568,7 @@ int mapif_parse_PartyLeaderChange(int fd, int party_id, int account_id, int char
p = inter_party->fromsql(party_id);
if(!p)
- return 0;
+ return false;
for (i = 0; i < MAX_PARTY; i++) {
if(p->party.member[i].leader)
@@ -745,10 +578,9 @@ int mapif_parse_PartyLeaderChange(int fd, int party_id, int account_id, int char
inter_party->tosql(&p->party,PS_LEADER, i);
}
}
- return 1;
+ return true;
}
-
// Communication from the map server
//-Analysis that only one packet
// Data packet length is set to inter.c that you
@@ -756,7 +588,7 @@ int mapif_parse_PartyLeaderChange(int fd, int party_id, int account_id, int char
// Return :
// 0 : error
// 1 : ok
-int inter_party_parse_frommap(int fd)
+static int inter_party_parse_frommap(int fd)
{
RFIFOHEAD(fd);
switch(RFIFOW(fd,0)) {
@@ -775,13 +607,7 @@ int inter_party_parse_frommap(int fd)
return 1;
}
-//Leave request from the server (for delete character)
-int inter_party_leave(int party_id,int account_id, int char_id)
-{
- return mapif->parse_PartyLeave(-1,party_id,account_id, char_id);
-}
-
-int inter_party_CharOnline(int char_id, int party_id)
+static int inter_party_CharOnline(int char_id, int party_id)
{
struct party_data* p;
int i;
@@ -828,7 +654,8 @@ int inter_party_CharOnline(int char_id, int party_id)
return 1;
}
-int inter_party_CharOffline(int char_id, int party_id) {
+static int inter_party_CharOffline(int char_id, int party_id)
+{
struct party_data *p=NULL;
int i;
@@ -895,4 +722,11 @@ void inter_party_defaults(void)
inter_party->leave = inter_party_leave;
inter_party->CharOnline = inter_party_CharOnline;
inter_party->CharOffline = inter_party_CharOffline;
+
+ inter_party->create = inter_party_create;
+ inter_party->add_member = inter_party_add_member;
+ inter_party->change_option = inter_party_change_option;
+ inter_party->change_map = inter_party_change_map;
+ inter_party->disband = inter_party_disband;
+ inter_party->change_leader = inter_party_change_leader;
}
diff --git a/src/char/int_party.h b/src/char/int_party.h
index 77363dd45..b9a888cca 100644
--- a/src/char/int_party.h
+++ b/src/char/int_party.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -60,9 +60,15 @@ struct inter_party_interface {
int (*check_exp_share) (struct party_data *p);
int (*check_empty) (struct party_data *p);
int (*parse_frommap) (int fd);
- int (*leave) (int party_id,int account_id, int char_id);
+ bool (*leave) (int party_id,int account_id, int char_id);
int (*CharOnline) (int char_id, int party_id);
int (*CharOffline) (int char_id, int party_id);
+ struct party_data *(*create) (const char *name, int item, int item2, const struct party_member *leader);
+ bool (*add_member) (int party_id, const struct party_member *member);
+ bool (*change_option) (int party_id, int account_id, int exp, int item, int map_fd);
+ bool (*change_map) (int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv);
+ bool (*disband) (int party_id);
+ bool (*change_leader) (int party_id, int account_id, int char_id);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_pet.c b/src/char/int_pet.c
index 489b10e3e..8f87becff 100644
--- a/src/char/int_pet.c
+++ b/src/char/int_pet.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -37,7 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_pet_interface inter_pet_s;
+static struct inter_pet_interface inter_pet_s;
struct inter_pet_interface *inter_pet;
/**
@@ -51,7 +51,7 @@ struct inter_pet_interface *inter_pet;
* @return The ID of the saved pet.
* @retval 0 in case of errors.
*/
-int inter_pet_tosql(const struct s_pet *p)
+static int inter_pet_tosql(const struct s_pet *p)
{
//`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`)
char esc_name[NAME_LENGTH*2+1];// escaped pet name
@@ -66,19 +66,19 @@ int inter_pet_tosql(const struct s_pet *p)
if (p->pet_id == 0) {
// New pet.
if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` "
- "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`) "
- "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
+ "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`) "
+ "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
- p->equip, intimate, hungry, p->rename_flag, p->incubate)) {
+ p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed)) {
Sql_ShowDebug(inter->sql_handle);
return 0;
}
pet_id = (int)SQL->LastInsertId(inter->sql_handle);
} else {
// Update pet.
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incubate`='%d' WHERE `pet_id`='%d'",
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incubate`='%d', `autofeed`='%d' WHERE `pet_id`='%d'",
pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
- p->equip, intimate, hungry, p->rename_flag, p->incubate, p->pet_id)) {
+ p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed, p->pet_id)) {
Sql_ShowDebug(inter->sql_handle);
return 0;
}
@@ -91,7 +91,7 @@ int inter_pet_tosql(const struct s_pet *p)
return pet_id;
}
-int inter_pet_fromsql(int pet_id, struct s_pet* p)
+static int inter_pet_fromsql(int pet_id, struct s_pet *p)
{
char* data;
size_t len;
@@ -102,9 +102,9 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p)
nullpo_ret(p);
memset(p, 0, sizeof(struct s_pet));
- //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`)
+ //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`)
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
+ if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`,`autofeed` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
{
Sql_ShowDebug(inter->sql_handle);
return 0;
@@ -124,6 +124,7 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p)
SQL->GetData(inter->sql_handle, 9, &data, NULL); p->hungry = atoi(data);
SQL->GetData(inter->sql_handle, 10, &data, NULL); p->rename_flag = atoi(data);
SQL->GetData(inter->sql_handle, 11, &data, NULL); p->incubate = atoi(data);
+ SQL->GetData(inter->sql_handle, 12, &data, NULL); p->autofeed = atoi(data);
SQL->FreeResult(inter->sql_handle);
@@ -137,17 +138,21 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p)
}
//----------------------------------------------
-int inter_pet_sql_init(void) {
+static int inter_pet_sql_init(void)
+{
//memory alloc
inter_pet->pt = (struct s_pet*)aCalloc(sizeof(struct s_pet), 1);
return 0;
}
-void inter_pet_sql_final(void) {
+
+static void inter_pet_sql_final(void)
+{
if (inter_pet->pt) aFree(inter_pet->pt);
return;
}
//----------------------------------
-int inter_pet_delete(int pet_id) {
+static int inter_pet_delete(int pet_id)
+{
ShowInfo("delete pet request: %d...\n",pet_id);
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
@@ -155,74 +160,8 @@ int inter_pet_delete(int pet_id) {
return 0;
}
//------------------------------------------------------
-int mapif_pet_created(int fd, int account_id, struct s_pet *p)
-{
- WFIFOHEAD(fd, 12);
- WFIFOW(fd, 0) = 0x3880;
- WFIFOL(fd, 2) = account_id;
- if(p!=NULL){
- WFIFOW(fd, 6) = p->class_;
- WFIFOL(fd, 8) = p->pet_id;
- ShowInfo("int_pet: created pet %d - %s\n", p->pet_id, p->name);
- }else{
- WFIFOB(fd, 6) = 0;
- WFIFOL(fd, 8) = 0;
- }
- WFIFOSET(fd, 12);
-
- return 0;
-}
-
-int mapif_pet_info(int fd, int account_id, struct s_pet *p)
-{
- nullpo_ret(p);
- WFIFOHEAD(fd, sizeof(struct s_pet) + 9);
- WFIFOW(fd, 0) =0x3881;
- WFIFOW(fd, 2) =sizeof(struct s_pet) + 9;
- WFIFOL(fd, 4) =account_id;
- WFIFOB(fd, 8)=0;
- memcpy(WFIFOP(fd, 9), p, sizeof(struct s_pet));
- WFIFOSET(fd, WFIFOW(fd, 2));
-
- return 0;
-}
-
-int mapif_pet_noinfo(int fd, int account_id)
-{
- WFIFOHEAD(fd, sizeof(struct s_pet) + 9);
- WFIFOW(fd, 0) =0x3881;
- WFIFOW(fd, 2) =sizeof(struct s_pet) + 9;
- WFIFOL(fd, 4) =account_id;
- WFIFOB(fd, 8)=1;
- memset(WFIFOP(fd, 9), 0, sizeof(struct s_pet));
- WFIFOSET(fd, WFIFOW(fd, 2));
-
- return 0;
-}
-
-int mapif_save_pet_ack(int fd, int account_id, int flag)
-{
- WFIFOHEAD(fd, 7);
- WFIFOW(fd, 0) =0x3882;
- WFIFOL(fd, 2) =account_id;
- WFIFOB(fd, 6) =flag;
- WFIFOSET(fd, 7);
-
- return 0;
-}
-
-int mapif_delete_pet_ack(int fd, int flag)
-{
- WFIFOHEAD(fd, 3);
- WFIFOW(fd, 0) =0x3883;
- WFIFOB(fd, 2) =flag;
- WFIFOSET(fd, 3);
-
- return 0;
-}
-
-int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short pet_lv, short pet_egg_id,
- short pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name)
+static struct s_pet *inter_pet_create(int account_id, int char_id, short pet_class, short pet_lv, int pet_egg_id,
+ int pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name)
{
nullpo_ret(pet_name);
memset(inter_pet->pt, 0, sizeof(struct s_pet));
@@ -253,90 +192,32 @@ int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short
inter_pet->pt->pet_id = 0; //Signal NEW pet.
if ((inter_pet->pt->pet_id = inter_pet->tosql(inter_pet->pt)) != 0)
- mapif->pet_created(fd, account_id, inter_pet->pt);
+ return inter_pet->pt;
else //Failed...
- mapif->pet_created(fd, account_id, NULL);
-
- return 0;
+ return NULL;
}
-int mapif_load_pet(int fd, int account_id, int char_id, int pet_id)
+static struct s_pet *inter_pet_load(int account_id, int char_id, int pet_id)
{
memset(inter_pet->pt, 0, sizeof(struct s_pet));
inter_pet->fromsql(pet_id, inter_pet->pt);
if(inter_pet->pt!=NULL) {
- if(inter_pet->pt->incubate == 1) {
+ if (inter_pet->pt->incubate == 1) {
inter_pet->pt->account_id = inter_pet->pt->char_id = 0;
- mapif->pet_info(fd, account_id, inter_pet->pt);
+ return inter_pet->pt;
+ } else if (account_id == inter_pet->pt->account_id && char_id == inter_pet->pt->char_id) {
+ return inter_pet->pt;
+ } else {
+ return NULL;
}
- else if(account_id == inter_pet->pt->account_id && char_id == inter_pet->pt->char_id)
- mapif->pet_info(fd, account_id, inter_pet->pt);
- else
- mapif->pet_noinfo(fd, account_id);
- }
- else
- mapif->pet_noinfo(fd, account_id);
-
- return 0;
-}
-
-int mapif_save_pet(int fd, int account_id, const struct s_pet *data)
-{
- //here process pet save request.
- int len;
- nullpo_ret(data);
- RFIFOHEAD(fd);
- len=RFIFOW(fd, 2);
- if (sizeof(struct s_pet) != len-8) {
- ShowError("inter pet: data size mismatch: %d != %"PRIuS"\n", len-8, sizeof(struct s_pet));
- return 0;
}
- inter_pet->tosql(data);
- mapif->save_pet_ack(fd, account_id, 0);
-
- return 0;
-}
-
-int mapif_delete_pet(int fd, int pet_id)
-{
- mapif->delete_pet_ack(fd, inter_pet->delete_(pet_id));
-
- return 0;
+ return NULL;
}
-int mapif_parse_CreatePet(int fd)
-{
- RFIFOHEAD(fd);
- mapif->create_pet(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOW(fd, 10), RFIFOW(fd, 12), RFIFOW(fd, 14), RFIFOW(fd, 16), RFIFOW(fd, 18),
- RFIFOW(fd, 20), RFIFOB(fd, 22), RFIFOB(fd, 23), RFIFOP(fd, 24));
- return 0;
-}
-
-int mapif_parse_LoadPet(int fd)
-{
- RFIFOHEAD(fd);
- mapif->load_pet(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10));
- return 0;
-}
-
-int mapif_parse_SavePet(int fd)
-{
- RFIFOHEAD(fd);
- mapif->save_pet(fd, RFIFOL(fd, 4), RFIFOP(fd, 8));
- return 0;
-}
-
-int mapif_parse_DeletePet(int fd)
-{
- RFIFOHEAD(fd);
- mapif->delete_pet(fd, RFIFOL(fd, 2));
- return 0;
-}
-
-int inter_pet_parse_frommap(int fd)
+static int inter_pet_parse_frommap(int fd)
{
RFIFOHEAD(fd);
switch(RFIFOW(fd, 0)){
@@ -362,4 +243,7 @@ void inter_pet_defaults(void)
inter_pet->sql_final = inter_pet_sql_final;
inter_pet->delete_ = inter_pet_delete;
inter_pet->parse_frommap = inter_pet_parse_frommap;
+
+ inter_pet->create = inter_pet_create;
+ inter_pet->load = inter_pet_load;
}
diff --git a/src/char/int_pet.h b/src/char/int_pet.h
index 13291e226..104771735 100644
--- a/src/char/int_pet.h
+++ b/src/char/int_pet.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -36,6 +36,10 @@ struct inter_pet_interface {
void (*sql_final) (void);
int (*delete_) (int pet_id);
int (*parse_frommap) (int fd);
+
+ struct s_pet *(*create) (int account_id, int char_id, short pet_class, short pet_lv, int pet_egg_id,
+ int pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name);
+ struct s_pet *(*load) (int account_id, int char_id, int pet_id);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_quest.c b/src/char/int_quest.c
index bd49cb7d4..0fa7771cb 100644
--- a/src/char/int_quest.c
+++ b/src/char/int_quest.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -37,7 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_quest_interface inter_quest_s;
+static struct inter_quest_interface inter_quest_s;
struct inter_quest_interface *inter_quest;
/**
@@ -48,7 +48,7 @@ struct inter_quest_interface *inter_quest;
* @return Array of found entries. It has *count entries, and it is care of the
* caller to aFree() it afterwards.
*/
-struct quest *mapif_quests_fromsql(int char_id, int *count)
+static struct quest *inter_quest_fromsql(int char_id, int *count)
{
struct quest *questlog = NULL;
struct quest tmp_quest;
@@ -56,6 +56,7 @@ struct quest *mapif_quests_fromsql(int char_id, int *count)
StringBuf buf;
int i;
int sqlerror = SQL_SUCCESS;
+ int quest_state = 0;
if (!count)
return NULL;
@@ -77,11 +78,11 @@ struct quest *mapif_quests_fromsql(int char_id, int *count)
memset(&tmp_quest, 0, sizeof(struct quest));
if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
- || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_quest.quest_id, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &tmp_quest.state, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &tmp_quest.time, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &tmp_quest.quest_id, sizeof tmp_quest.quest_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &quest_state, sizeof quest_state, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &tmp_quest.time, sizeof tmp_quest.time, NULL, NULL)
) {
sqlerror = SQL_ERROR;
}
@@ -89,7 +90,7 @@ struct quest *mapif_quests_fromsql(int char_id, int *count)
StrBuf->Destroy(&buf);
for (i = 0; sqlerror != SQL_ERROR && i < MAX_QUEST_OBJECTIVES; i++) { // Stop on the first error
- sqlerror = SQL->StmtBindColumn(stmt, 3+i, SQLDT_INT, &tmp_quest.count[i], 0, NULL, NULL);
+ sqlerror = SQL->StmtBindColumn(stmt, 3+i, SQLDT_INT, &tmp_quest.count[i], sizeof tmp_quest.count[i], NULL, NULL);
}
if (sqlerror == SQL_ERROR) {
@@ -105,9 +106,10 @@ struct quest *mapif_quests_fromsql(int char_id, int *count)
questlog = (struct quest *)aCalloc(*count, sizeof(struct quest));
while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+ tmp_quest.state = quest_state;
if (i >= *count) // Sanity check, should never happen
break;
- memcpy(&questlog[i++], &tmp_quest, sizeof(tmp_quest));
+ questlog[i++] = tmp_quest;
}
if (i < *count) {
// Should never happen. Compact array
@@ -127,7 +129,7 @@ struct quest *mapif_quests_fromsql(int char_id, int *count)
* @param quest_id Quest ID
* @return false in case of errors, true otherwise
*/
-bool mapif_quest_delete(int char_id, int quest_id)
+static bool inter_quest_delete(int char_id, int quest_id)
{
if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id)) {
Sql_ShowDebug(inter->sql_handle);
@@ -144,7 +146,7 @@ bool mapif_quest_delete(int char_id, int quest_id)
* @param qd Quest data
* @return false in case of errors, true otherwise
*/
-bool mapif_quest_add(int char_id, struct quest qd)
+static bool inter_quest_add(int char_id, struct quest qd)
{
StringBuf buf;
int i;
@@ -176,7 +178,7 @@ bool mapif_quest_add(int char_id, struct quest qd)
* @param qd Quest data
* @return false in case of errors, true otherwise
*/
-bool mapif_quest_update(int char_id, struct quest qd)
+static bool inter_quest_update(int char_id, struct quest qd)
{
StringBuf buf;
int i;
@@ -198,34 +200,13 @@ bool mapif_quest_update(int char_id, struct quest qd)
return true;
}
-void mapif_quest_save_ack(int fd, int char_id, bool success)
+static bool inter_quest_save(int char_id, const struct quest *new_qd, int new_n)
{
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x3861;
- WFIFOL(fd,2) = char_id;
- WFIFOB(fd,6) = success?1:0;
- WFIFOSET(fd,7);
-}
-
-/**
- * Handles the save request from mapserver for a character's questlog.
- *
- * Received quests are saved, and an ack is sent back to the map server.
- *
- * @see inter_parse_frommap
- */
-int mapif_parse_quest_save(int fd)
-{
- int i, j, k, old_n, new_n = (RFIFOW(fd,2)-8)/sizeof(struct quest);
- int char_id = RFIFOL(fd,4);
+ int i, j, k, old_n;
struct quest *old_qd = NULL;
- const struct quest *new_qd = NULL;
bool success = true;
- if (new_n > 0)
- new_qd = RFIFOP(fd,8);
-
- old_qd = mapif->quests_fromsql(char_id, &old_n);
+ old_qd = inter_quest->fromsql(char_id, &old_n);
for (i = 0; i < new_n; i++) {
ARR_FIND( 0, old_n, j, new_qd[i].quest_id == old_qd[j].quest_id );
@@ -235,7 +216,7 @@ int mapif_parse_quest_save(int fd)
// Only states and counts are changeable.
ARR_FIND( 0, MAX_QUEST_OBJECTIVES, k, new_qd[i].count[k] != old_qd[j].count[k] );
if (k != MAX_QUEST_OBJECTIVES || new_qd[i].state != old_qd[j].state)
- success &= mapif->quest_update(char_id, new_qd[i]);
+ success &= inter_quest->update(char_id, new_qd[i]);
if (j < (--old_n)) {
// Compact array
@@ -244,59 +225,17 @@ int mapif_parse_quest_save(int fd)
}
} else {
// Add new quests
- success &= mapif->quest_add(char_id, new_qd[i]);
+ success &= inter_quest->add(char_id, new_qd[i]);
}
}
for (i = 0; i < old_n; i++) // Quests not in new_qd but in old_qd are to be erased.
- success &= mapif->quest_delete(char_id, old_qd[i].quest_id);
+ success &= inter_quest->delete(char_id, old_qd[i].quest_id);
if (old_qd)
aFree(old_qd);
- // Send ack
- mapif->quest_save_ack(fd, char_id, success);
-
- return 0;
-}
-
-void mapif_send_quests(int fd, int char_id, struct quest *tmp_questlog, int num_quests)
-{
- WFIFOHEAD(fd,num_quests*sizeof(struct quest)+8);
- WFIFOW(fd,0) = 0x3860;
- WFIFOW(fd,2) = num_quests*sizeof(struct quest)+8;
- WFIFOL(fd,4) = char_id;
-
- if (num_quests > 0) {
- nullpo_retv(tmp_questlog);
- memcpy(WFIFOP(fd,8), tmp_questlog, sizeof(struct quest)*num_quests);
- }
-
- WFIFOSET(fd,num_quests*sizeof(struct quest)+8);
-}
-
-/**
- * Sends questlog to the map server
- *
- * Note: Completed quests (state == Q_COMPLETE) are guaranteed to be sent last
- * and the map server relies on this behavior (once the first Q_COMPLETE quest,
- * all of them are considered to be Q_COMPLETE)
- *
- * @see inter_parse_frommap
- */
-int mapif_parse_quest_load(int fd)
-{
- int char_id = RFIFOL(fd,2);
- struct quest *tmp_questlog = NULL;
- int num_quests;
-
- tmp_questlog = mapif->quests_fromsql(char_id, &num_quests);
- mapif->send_quests(fd, char_id, tmp_questlog, num_quests);
-
- if (tmp_questlog)
- aFree(tmp_questlog);
-
- return 0;
+ return success;
}
/**
@@ -304,7 +243,7 @@ int mapif_parse_quest_load(int fd)
*
* @see inter_parse_frommap
*/
-int inter_quest_parse_frommap(int fd)
+static int inter_quest_parse_frommap(int fd)
{
switch(RFIFOW(fd,0)) {
case 0x3060: mapif->parse_quest_load(fd); break;
@@ -320,4 +259,9 @@ void inter_quest_defaults(void)
inter_quest = &inter_quest_s;
inter_quest->parse_frommap = inter_quest_parse_frommap;
+ inter_quest->fromsql = inter_quest_fromsql;
+ inter_quest->delete = inter_quest_delete;
+ inter_quest->add = inter_quest_add;
+ inter_quest->update = inter_quest_update;
+ inter_quest->save = inter_quest_save;
}
diff --git a/src/char/int_quest.h b/src/char/int_quest.h
index 737213fff..e71afc561 100644
--- a/src/char/int_quest.h
+++ b/src/char/int_quest.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -28,6 +28,12 @@
**/
struct inter_quest_interface {
int (*parse_frommap) (int fd);
+
+ struct quest *(*fromsql) (int char_id, int *count);
+ bool (*delete) (int char_id, int quest_id);
+ bool (*add) (int char_id, struct quest qd);
+ bool (*update) (int char_id, struct quest qd);
+ bool (*save) (int char_id, const struct quest *new_qd, int new_n);
};
#ifdef HERCULES_CORE
diff --git a/src/char/int_rodex.c b/src/char/int_rodex.c
new file mode 100644
index 000000000..18c277574
--- /dev/null
+++ b/src/char/int_rodex.c
@@ -0,0 +1,432 @@
+/**
+ * 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 "int_rodex.h"
+
+#include "char/char.h"
+#include "char/inter.h"
+#include "char/mapif.h"
+#include "common/db.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>
+
+static struct inter_rodex_interface inter_rodex_s;
+struct inter_rodex_interface *inter_rodex;
+
+// Loads new mails of this char_id/account_id
+static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 mail_id, struct rodex_maillist *mails)
+{
+ int count = 0;
+ struct rodex_message msg = { 0 };
+ struct SqlStmt *stmt;
+
+ nullpo_retr(-1, mails);
+
+ stmt = SQL->StmtMalloc(inter->sql_handle);
+
+ switch (opentype) {
+ 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`, `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)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+ break;
+
+ 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`, `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)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+ break;
+
+ 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`, `sender_read`, `send_date`, `expire_date`, `weight`"
+ "FROM `%s` WHERE (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `expire_date` + '%d' > '%d' AND `mail_id` > '%"PRId64"')"
+ "ORDER BY `mail_id` ASC", rodex_db, char_id, (int)time(NULL), RODEX_EXPIRE, (int)time(NULL), mail_id)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+ break;
+
+ 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`, `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 `expire_date` + '%d' > '%d'))"
+ "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, account_id, char_id, (int)time(NULL), RODEX_EXPIRE, (int)time(NULL))
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+ break;
+ }
+
+ if (SQL_ERROR == SQL->StmtExecute(stmt)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT64, &msg.id, sizeof msg.id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_STRING, &msg.sender_name, sizeof msg.sender_name, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &msg.sender_id, sizeof msg.sender_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_STRING, &msg.receiver_name, sizeof msg.receiver_name, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT, &msg.receiver_id, sizeof msg.receiver_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &msg.receiver_accountid, sizeof msg.receiver_accountid, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_STRING, &msg.title, sizeof msg.title, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_STRING, &msg.body, sizeof msg.body, NULL, NULL)
+ || 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_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);
+ return -1;
+ }
+
+ {
+ struct item it = { 0 };
+ StringBuf buf;
+ struct SqlStmt *stmt_items = SQL->StmtMalloc(inter->sql_handle);
+ int i;
+
+ if (stmt_items == NULL) {
+ SQL->StmtFreeResult(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+
+ StrBuf->Init(&buf);
+
+ StrBuf->AppendStr(&buf, "SELECT `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
+ for (i = 0; i < MAX_SLOTS; i++) {
+ StrBuf->Printf(&buf, ", `card%d`", i);
+ }
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i);
+ }
+ StrBuf->Printf(&buf, "FROM `%s` WHERE mail_id = ? ORDER BY `mail_id` ASC", rodex_item_db);
+
+ if (SQL_ERROR == SQL->StmtPrepareStr(stmt_items, StrBuf->Value(&buf))
+ || SQL_ERROR == SQL->StmtBindParam(stmt_items, 0, SQLDT_INT64, &msg.id, sizeof msg.id)
+ ) {
+ SqlStmt_ShowDebug(stmt_items);
+ }
+
+ // Read mails
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+
+ if (msg.type & MAIL_TYPE_ITEM) {
+ if (SQL_ERROR == SQL->StmtExecute(stmt_items)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 0, SQLDT_INT, &it.nameid, sizeof it.nameid, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 1, SQLDT_SHORT, &it.amount, sizeof it.amount, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 2, SQLDT_UINT, &it.equip, sizeof it.equip, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 3, SQLDT_CHAR, &it.identify, sizeof it.identify, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 4, SQLDT_CHAR, &it.refine, sizeof it.refine, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 5, SQLDT_CHAR, &it.attribute, sizeof it.attribute, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 6, SQLDT_UINT, &it.expire_time, sizeof it.expire_time, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 7, SQLDT_UCHAR, &it.bound, sizeof it.bound, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 8, SQLDT_UINT64, &it.unique_id, sizeof it.unique_id, NULL, NULL)
+ ) {
+ SqlStmt_ShowDebug(stmt_items);
+ }
+ for (i = 0; i < MAX_SLOTS; i++) {
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + i, SQLDT_INT, &it.card[i], sizeof it.card[i], NULL, NULL))
+ SqlStmt_ShowDebug(stmt_items);
+ }
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].index, sizeof it.option[i].index, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 10 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].value, sizeof it.option[i].value, NULL, NULL)
+ ) {
+ SqlStmt_ShowDebug(stmt_items);
+ }
+ }
+
+ for (i = 0; i < RODEX_MAX_ITEM && SQL_SUCCESS == SQL->StmtNextRow(stmt_items); ++i) {
+ msg.items[i].item = it;
+ msg.items_count++;
+ }
+ }
+
+ if (msg.items_count == 0) {
+ msg.type &= ~MAIL_TYPE_ITEM;
+ }
+
+ if (msg.zeny == 0) {
+ msg.type &= ~MAIL_TYPE_ZENY;
+ }
+
+#if PACKETVER >= 20170419
+ if (opentype == RODEX_OPENTYPE_UNSET) {
+ 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;
+ }
+#else
+ msg.opentype = opentype;
+#endif
+#if PACKETVER < 20160601
+ // NPC Message Type isn't supported in old clients
+ msg.type &= ~MAIL_TYPE_NPC;
+#endif
+
+ ++count;
+ VECTOR_ENSURE(*mails, 1, 1);
+ VECTOR_PUSH(*mails, msg);
+ memset(&msg, 0, sizeof(struct rodex_message));
+
+ SQL->StmtFreeResult(stmt_items);
+ }
+ StrBuf->Destroy(&buf);
+ SQL->StmtFree(stmt_items);
+ }
+
+ SQL->StmtFreeResult(stmt);
+ SQL->StmtFree(stmt);
+
+ ShowInfo("rodex load complete from DB - id: %d (total: %d)\n", char_id, count);
+ return count;
+}
+
+// Checks if user has non-read mails
+static bool inter_rodex_hasnew(int char_id, int account_id)
+{
+ int count = 0;
+ char *data;
+
+ 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)" // 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))
+ ) {
+ Sql_ShowDebug(inter->sql_handle);
+ return -1;
+ }
+
+ if (SQL_SUCCESS != SQL->NextRow(inter->sql_handle))
+ return false;
+
+ SQL->GetData(inter->sql_handle, 0, &data, NULL);
+ count = atoi(data);
+ SQL->FreeResult(inter->sql_handle);
+
+ return count > 0;
+}
+
+/// Checks player name and retrieves some data
+static bool inter_rodex_checkname(const char *name, int *target_char_id, short *target_class, int *target_level)
+{
+ char esc_name[NAME_LENGTH * 2 + 1];
+ bool found = false;
+
+ nullpo_retr(false, name);
+ nullpo_retr(false, target_char_id);
+ nullpo_retr(false, target_class);
+ nullpo_retr(false, target_level);
+
+ // Try to find the Dest Char by Name
+ SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `char_id`, `class`, `base_level` FROM `%s` WHERE `name` = '%s'", char_db, esc_name)) {
+ Sql_ShowDebug(inter->sql_handle);
+ } else {
+ if (SQL_SUCCESS == SQL->NextRow(inter->sql_handle)) {
+ char *data;
+ SQL->GetData(inter->sql_handle, 0, &data, NULL); *target_char_id = atoi(data);
+ SQL->GetData(inter->sql_handle, 1, &data, NULL); *target_class = (short)atoi(data);
+ SQL->GetData(inter->sql_handle, 2, &data, NULL); *target_level = atoi(data);
+ found = true;
+ }
+ }
+ SQL->FreeResult(inter->sql_handle);
+
+ return found;
+}
+
+/// Stores a single message in the database.
+/// Returns the message's ID if successful (or 0 if it fails).
+static int64 inter_rodex_savemessage(struct rodex_message *msg)
+{
+ char sender_name[NAME_LENGTH * 2 + 1];
+ char receiver_name[NAME_LENGTH * 2 + 1];
+ char body[RODEX_BODY_LENGTH * 2 + 1];
+ char title[RODEX_TITLE_LENGTH * 2 + 1];
+ int i;
+
+ nullpo_retr(false, msg);
+
+ SQL->EscapeStringLen(inter->sql_handle, sender_name, msg->sender_name, strnlen(msg->sender_name, NAME_LENGTH));
+ SQL->EscapeStringLen(inter->sql_handle, receiver_name, msg->receiver_name, strnlen(msg->receiver_name, NAME_LENGTH));
+ SQL->EscapeStringLen(inter->sql_handle, body, msg->body, strnlen(msg->body, RODEX_BODY_LENGTH));
+ 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`, `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->sender_read == true ? 1 : 0, msg->send_date, msg->expire_date, msg->weight)) {
+ Sql_ShowDebug(inter->sql_handle);
+ return 0;
+ }
+
+ msg->id = (int64)SQL->LastInsertId(inter->sql_handle);
+
+ for (i = 0; i < RODEX_MAX_ITEM; ++i) {
+ // Should we use statement here? [KIRIEZ]
+ struct item *it = &msg->items[i].item;
+ if (it->nameid == 0)
+ continue;
+
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` (`mail_id`, `nameid`, `amount`, `equip`, `identify`,"
+ "`refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `opt_idx0`, `opt_val0`, `opt_idx1`, `opt_val1`, `opt_idx2`,"
+ "`opt_val2`, `opt_idx3`, `opt_val3`, `opt_idx4`, `opt_val4`,`expire_time`, `bound`, `unique_id`) VALUES "
+ "('%"PRId64"', '%d', '%d', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%u', '%"PRIu64"')",
+ rodex_item_db, msg->id, it->nameid, it->amount, it->equip, it->identify, it->refine, it->attribute, it->card[0], it->card[1], it->card[2], it->card[3],
+ it->option[0].index, it->option[0].value, it->option[1].index, it->option[1].value, it->option[2].index, it->option[2].value, it->option[3].index,
+ it->option[3].value, it->option[4].index, it->option[4].value, it->expire_time, it->bound, it->unique_id)
+ ) {
+ Sql_ShowDebug(inter->sql_handle);
+ continue;
+ }
+ }
+
+ return msg->id;
+}
+
+/*==========================================
+ * Update/Delete mail
+ *------------------------------------------*/
+static bool inter_rodex_updatemail(int64 mail_id, int8 flag)
+{
+ Assert_retr(false, mail_id > 0);
+ Assert_retr(false, flag >= 0 && flag <= 4);
+
+ switch (flag) {
+ case 0: // Read
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `is_read` = 1 WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ break;
+
+ case 1: // Get Zeny
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `zeny` = 0, `type` = `type` & (~2) WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ break;
+
+ case 2: // Get Items
+ 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);
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `zeny` = 0, `type` = `type` & (~4) WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ break;
+
+ case 3: // Delete Mail
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ 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;
+ default:
+ return false;
+ }
+ return true;
+}
+
+/*==========================================
+ * Packets From Map Server
+ *------------------------------------------*/
+static int inter_rodex_parse_frommap(int fd)
+{
+ switch(RFIFOW(fd,0))
+ {
+ case 0x3095: mapif->parse_rodex_requestinbox(fd); break;
+ case 0x3096: mapif->parse_rodex_checkhasnew(fd); break;
+ case 0x3097: mapif->parse_rodex_updatemail(fd); break;
+ case 0x3098: mapif->parse_rodex_send(fd); break;
+ case 0x3099: mapif->parse_rodex_checkname(fd); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int inter_rodex_sql_init(void)
+{
+ return 1;
+}
+
+static void inter_rodex_sql_final(void)
+{
+ return;
+}
+
+void inter_rodex_defaults(void)
+{
+ inter_rodex = &inter_rodex_s;
+
+ inter_rodex->savemessage = inter_rodex_savemessage;
+ inter_rodex->parse_frommap = inter_rodex_parse_frommap;
+ inter_rodex->sql_init = inter_rodex_sql_init;
+ inter_rodex->sql_final = inter_rodex_sql_final;
+ inter_rodex->fromsql = inter_rodex_fromsql;
+ inter_rodex->hasnew = inter_rodex_hasnew;
+ inter_rodex->checkname = inter_rodex_checkname;
+ inter_rodex->updatemail = inter_rodex_updatemail;
+}
diff --git a/src/char/int_rodex.h b/src/char/int_rodex.h
new file mode 100644
index 000000000..43e2d891c
--- /dev/null
+++ b/src/char/int_rodex.h
@@ -0,0 +1,48 @@
+/**
+ * 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_RODEX_H
+#define CHAR_INT_RODEX_H
+
+#include "common/mmo.h"
+#include "common/db.h"
+
+struct item;
+
+/**
+ * inter_rodex interface
+ **/
+struct inter_rodex_interface {
+ int (*sql_init) (void);
+ void (*sql_final) (void);
+ int (*parse_frommap) (int fd);
+ int (*fromsql) (int char_id, int account_id, int8 opentype, int64 mail_id, struct rodex_maillist *mails);
+ bool (*hasnew) (int char_id, int account_id);
+ bool (*checkname) (const char *name, int *target_char_id, short *target_class, int *target_level);
+ int64 (*savemessage) (struct rodex_message* msg);
+ bool (*updatemail) (int64 mail_id, int8 flag);
+};
+
+#ifdef HERCULES_CORE
+void inter_rodex_defaults(void);
+#endif // HERCULES_CORE
+
+HPShared struct inter_rodex_interface *inter_rodex;
+
+#endif /* CHAR_INT_RODEX_H */
diff --git a/src/char/int_storage.c b/src/char/int_storage.c
index 8e3ebdff3..130df5515 100644
--- a/src/char/int_storage.c
+++ b/src/char/int_storage.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -37,34 +37,154 @@
#include <stdio.h>
#include <stdlib.h>
-struct inter_storage_interface inter_storage_s;
+static struct inter_storage_interface inter_storage_s;
struct inter_storage_interface *inter_storage;
/// Save storage data to sql
-int inter_storage_tosql(int account_id, struct storage_data* p)
+static int inter_storage_tosql(int account_id, const struct storage_data *p)
{
+ int i = 0, j = 0;
+ bool matched_p[MAX_STORAGE] = { false };
+ int delete[MAX_STORAGE] = { 0 };
+ int total_deletes = 0, total_updates = 0, total_inserts = 0;
+ int total_changes = 0;
+ struct storage_data cp = { 0 };
+ StringBuf buf;
+
nullpo_ret(p);
- chr->memitemdata_to_sql(p->items, MAX_STORAGE, account_id, TABLE_STORAGE);
- return 0;
+
+ VECTOR_INIT(cp.item);
+ inter_storage->fromsql(account_id, &cp);
+
+ StrBuf->Init(&buf);
+
+ if (VECTOR_LENGTH(cp.item) > 0) {
+ /**
+ * Compare and update items, if any.
+ */
+ for (i = 0; i < VECTOR_LENGTH(cp.item); i++) {
+ struct item *cp_it = &VECTOR_INDEX(cp.item, i);
+ struct item *p_it = NULL;
+
+ ARR_FIND(0, VECTOR_LENGTH(p->item), j,
+ matched_p[j] != true
+ && (p_it = &VECTOR_INDEX(p->item, j)) != NULL
+ && cp_it->nameid == p_it->nameid
+ && cp_it->unique_id == p_it->unique_id
+ && memcmp(p_it->card, cp_it->card, sizeof(int) * MAX_SLOTS) == 0
+ && memcmp(p_it->option, cp_it->option, 5 * MAX_ITEM_OPTIONS) == 0);
+
+ if (j < VECTOR_LENGTH(p->item)) {
+ int k = 0;
+ if (memcmp(cp_it, p_it, sizeof(struct item)) != 0) {
+ if (total_updates == 0) {
+ StrBuf->Printf(&buf, "REPLACE INTO `%s` (`id`, `account_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", storage_db);
+ for (k = 0; k < MAX_SLOTS; k++)
+ StrBuf->Printf(&buf, ", `card%d`", k);
+ for (k = 0; k < MAX_ITEM_OPTIONS; k++)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", k, k);
+ StrBuf->AppendStr(&buf, ", `expire_time`, `bound`, `unique_id`) VALUES");
+ }
+
+ StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%d', '%u', '%d', '%d', '%d'",
+ total_updates > 0 ? ", " : "", cp_it->id, account_id, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine, p_it->attribute);
+ for (k = 0; k < MAX_SLOTS; k++)
+ StrBuf->Printf(&buf, ", '%d'", p_it->card[k]);
+ for (k = 0; k < MAX_ITEM_OPTIONS; ++k)
+ StrBuf->Printf(&buf, ", '%d', '%d'", p_it->option[k].index, p_it->option[k].value);
+ StrBuf->Printf(&buf, ", '%u', '%d', '%"PRIu64"')", p_it->expire_time, p_it->bound, p_it->unique_id);
+
+ total_updates++;
+ }
+ matched_p[j] = true;
+ } else { // Does not exist, so set for deletion.
+ delete[total_deletes++] = cp_it->id;
+ }
+ }
+
+ if (total_updates > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
+ Sql_ShowDebug(inter->sql_handle);
+
+ /**
+ * Handle deletions, if any.
+ */
+ if (total_deletes > 0) {
+ StrBuf->Clear(&buf);
+ StrBuf->Printf(&buf, "DELETE FROM `%s` WHERE `id` IN (", storage_db);
+ for (i = 0; i < total_deletes; i++) {
+ StrBuf->Printf(&buf, "%s'%d'", i == 0 ? "" : ", ", delete[i]);
+ }
+ StrBuf->AppendStr(&buf, ");");
+
+ if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
+ Sql_ShowDebug(inter->sql_handle);
+ }
+ }
+
+ /**
+ * Check for new items.
+ */
+ for (i = 0; i < VECTOR_LENGTH(p->item); i++) {
+ struct item *p_it = &VECTOR_INDEX(p->item, i);
+
+ if (matched_p[i])
+ continue; // Item is not a new entry, so lets continue.
+
+ // Store the remaining items.
+ if (total_inserts == 0) {
+ StrBuf->Clear(&buf);
+ StrBuf->Printf(&buf, "INSERT INTO `%s` (`account_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", storage_db);
+ for (j = 0; j < MAX_SLOTS; ++j)
+ StrBuf->Printf(&buf, ", `card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j);
+ StrBuf->AppendStr(&buf, ") VALUES ");
+ }
+
+ StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'",
+ total_inserts > 0 ? ", " : "", account_id, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine,
+ p_it->attribute, p_it->expire_time, p_it->bound, p_it->unique_id);
+ for (j = 0; j < MAX_SLOTS; ++j)
+ StrBuf->Printf(&buf, ", '%d'", p_it->card[j]);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", '%d', '%d'", p_it->option[j].index, p_it->option[j].value);
+ StrBuf->AppendStr(&buf, ")");
+
+ total_inserts++;
+ }
+
+ if (total_inserts > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
+ Sql_ShowDebug(inter->sql_handle);
+
+ StrBuf->Destroy(&buf);
+ VECTOR_CLEAR(cp.item);
+
+ total_changes = total_inserts + total_updates + total_deletes;
+ ShowInfo("storage save complete - id: %d (total: %d)\n", account_id, total_changes);
+ return total_changes;
}
/// Load storage data to mem
-int inter_storage_fromsql(int account_id, struct storage_data* p)
+static int inter_storage_fromsql(int account_id, struct storage_data *p)
{
StringBuf buf;
char* data;
int i;
int j;
+ int num_rows = 0;
nullpo_ret(p);
- memset(p, 0, sizeof(struct storage_data)); //clean up memory
- p->storage_amount = 0;
+
+ if (VECTOR_LENGTH(p->item) > 0)
+ VECTOR_CLEAR(p->item);
// storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`}
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`bound`,`unique_id`");
- for( j = 0; j < MAX_SLOTS; ++j )
+ for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ",`card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ",`opt_idx%d`,`opt_val%d`", j, j);
StrBuf->Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id);
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
@@ -72,41 +192,70 @@ int inter_storage_fromsql(int account_id, struct storage_data* p)
StrBuf->Destroy(&buf);
- for (i = 0; i < MAX_STORAGE && SQL_SUCCESS == SQL->NextRow(inter->sql_handle); ++i) {
- struct item *item = &p->items[i];
- SQL->GetData(inter->sql_handle, 0, &data, NULL); item->id = atoi(data);
- SQL->GetData(inter->sql_handle, 1, &data, NULL); item->nameid = atoi(data);
- SQL->GetData(inter->sql_handle, 2, &data, NULL); item->amount = atoi(data);
- SQL->GetData(inter->sql_handle, 3, &data, NULL); item->equip = atoi(data);
- SQL->GetData(inter->sql_handle, 4, &data, NULL); item->identify = atoi(data);
- SQL->GetData(inter->sql_handle, 5, &data, NULL); item->refine = atoi(data);
- SQL->GetData(inter->sql_handle, 6, &data, NULL); item->attribute = atoi(data);
- SQL->GetData(inter->sql_handle, 7, &data, NULL); item->expire_time = (unsigned int)atoi(data);
- SQL->GetData(inter->sql_handle, 8, &data, NULL); item->bound = atoi(data);
- SQL->GetData(inter->sql_handle, 9, &data, NULL); item->unique_id = strtoull(data, NULL, 10);
- for( j = 0; j < MAX_SLOTS; ++j )
- {
- SQL->GetData(inter->sql_handle, 10+j, &data, NULL); item->card[j] = atoi(data);
+ if ((num_rows = (int)SQL->NumRows(inter->sql_handle)) != 0) {
+
+ VECTOR_ENSURE(p->item, num_rows > MAX_STORAGE ? MAX_STORAGE : num_rows, 1);
+
+ for (i = 0; i < MAX_STORAGE && SQL_SUCCESS == SQL->NextRow(inter->sql_handle); ++i) {
+ struct item item = { 0 };
+ SQL->GetData(inter->sql_handle, 0, &data, NULL); item.id = atoi(data);
+ SQL->GetData(inter->sql_handle, 1, &data, NULL); item.nameid = atoi(data);
+ SQL->GetData(inter->sql_handle, 2, &data, NULL); item.amount = atoi(data);
+ SQL->GetData(inter->sql_handle, 3, &data, NULL); item.equip = atoi(data);
+ SQL->GetData(inter->sql_handle, 4, &data, NULL); item.identify = atoi(data);
+ SQL->GetData(inter->sql_handle, 5, &data, NULL); item.refine = atoi(data);
+ SQL->GetData(inter->sql_handle, 6, &data, NULL); item.attribute = atoi(data);
+ SQL->GetData(inter->sql_handle, 7, &data, NULL); item.expire_time = (unsigned int)atoi(data);
+ SQL->GetData(inter->sql_handle, 8, &data, NULL); item.bound = atoi(data);
+ SQL->GetData(inter->sql_handle, 9, &data, NULL); item.unique_id = strtoull(data, NULL, 10);
+
+ /* Card Slots */
+ for (j = 0; j < MAX_SLOTS; ++j) {
+ SQL->GetData(inter->sql_handle, 10 + j, &data, NULL);
+ item.card[j] = atoi(data);
+ }
+
+ /* Item Options */
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j) {
+ SQL->GetData(inter->sql_handle, 10 + MAX_SLOTS + j * 2, &data, NULL);
+ item.option[j].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 11 + MAX_SLOTS + j * 2, &data, NULL);
+ item.option[j].value = atoi(data);
+ }
+
+ VECTOR_PUSH(p->item, item);
}
}
- p->storage_amount = i;
+
SQL->FreeResult(inter->sql_handle);
- ShowInfo("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount);
- return 1;
+ ShowInfo("storage load complete from DB - id: %d (total: %d)\n", account_id, VECTOR_LENGTH(p->item));
+
+ return VECTOR_LENGTH(p->item);
}
/// Save guild_storage data to sql
-int inter_storage_guild_storage_tosql(int guild_id, const struct guild_storage *p)
+static bool inter_storage_guild_storage_tosql(int guild_id, const struct guild_storage *p)
{
nullpo_ret(p);
- chr->memitemdata_to_sql(p->items, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE);
+
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id)) {
+ Sql_ShowDebug(inter->sql_handle);
+ return false;
+ } else if (SQL->NumRows(inter->sql_handle) < 1) {
+ // guild doesn't exist
+ SQL->FreeResult(inter->sql_handle);
+ return false;
+ }
+ SQL->FreeResult(inter->sql_handle);
+
+ chr->memitemdata_to_sql(p->items, guild_id, TABLE_GUILD_STORAGE);
ShowInfo ("guild storage save to DB - guild: %d\n", guild_id);
- return 0;
+ return true;
}
/// Load guild_storage data to mem
-int inter_storage_guild_storage_fromsql(int guild_id, struct guild_storage* p)
+static int inter_storage_guild_storage_fromsql(int guild_id, struct guild_storage* p)
{
StringBuf buf;
char* data;
@@ -121,8 +270,10 @@ int inter_storage_guild_storage_fromsql(int guild_id, struct guild_storage* p)
// storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`}
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`bound`,`unique_id`");
- for( j = 0; j < MAX_SLOTS; ++j )
+ for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ",`card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j);
StrBuf->Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id);
if( SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
@@ -142,9 +293,17 @@ int inter_storage_guild_storage_fromsql(int guild_id, struct guild_storage* p)
SQL->GetData(inter->sql_handle, 7, &data, NULL); item->bound = atoi(data);
SQL->GetData(inter->sql_handle, 8, &data, NULL); item->unique_id = strtoull(data, NULL, 10);
item->expire_time = 0;
-
- for( j = 0; j < MAX_SLOTS; ++j ) {
- SQL->GetData(inter->sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data);
+ /* Card Slots */
+ for (j = 0; j < MAX_SLOTS; ++j) {
+ SQL->GetData(inter->sql_handle, 9 + j, &data, NULL);
+ item->card[j] = atoi(data);
+ }
+ /* Item Options */
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j) {
+ SQL->GetData(inter->sql_handle, 9 + MAX_SLOTS + j * 2, &data, NULL);
+ item->option[j].index = atoi(data);
+ SQL->GetData(inter->sql_handle, 10 + MAX_SLOTS + j * 2, &data, NULL);
+ item->option[j].value = atoi(data);
}
}
p->storage_amount = i;
@@ -156,124 +315,35 @@ int inter_storage_guild_storage_fromsql(int guild_id, struct guild_storage* p)
//---------------------------------------------------------
// storage data initialize
-int inter_storage_sql_init(void)
+static int inter_storage_sql_init(void)
{
return 1;
}
// storage data finalize
-void inter_storage_sql_final(void)
+static void inter_storage_sql_final(void)
{
return;
}
// q?f[^?
-int inter_storage_delete(int account_id)
+static int inter_storage_delete(int account_id)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) )
Sql_ShowDebug(inter->sql_handle);
return 0;
}
-int inter_storage_guild_storage_delete(int guild_id)
+static int inter_storage_guild_storage_delete(int guild_id)
{
if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) )
Sql_ShowDebug(inter->sql_handle);
return 0;
}
-//---------------------------------------------------------
-// packet from map server
-
-int mapif_load_guild_storage(int fd, int account_id, int guild_id, char flag)
-{
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
- Sql_ShowDebug(inter->sql_handle);
- else if( SQL->NumRows(inter->sql_handle) > 0 )
- {// guild exists
- WFIFOHEAD(fd, sizeof(struct guild_storage)+13);
- WFIFOW(fd,0) = 0x3818;
- WFIFOW(fd,2) = sizeof(struct guild_storage)+13;
- WFIFOL(fd,4) = account_id;
- WFIFOL(fd,8) = guild_id;
- WFIFOB(fd,12) = flag; //1 open storage, 0 don't open
- inter_storage->guild_storage_fromsql(guild_id, WFIFOP(fd,13));
- WFIFOSET(fd, WFIFOW(fd,2));
- return 0;
- }
- // guild does not exist
- SQL->FreeResult(inter->sql_handle);
- WFIFOHEAD(fd, 12);
- WFIFOW(fd,0) = 0x3818;
- WFIFOW(fd,2) = 12;
- WFIFOL(fd,4) = account_id;
- WFIFOL(fd,8) = 0;
- WFIFOSET(fd, 12);
- return 0;
-}
-int mapif_save_guild_storage_ack(int fd, int account_id, int guild_id, int fail)
-{
- WFIFOHEAD(fd,11);
- WFIFOW(fd,0)=0x3819;
- WFIFOL(fd,2)=account_id;
- WFIFOL(fd,6)=guild_id;
- WFIFOB(fd,10)=fail;
- WFIFOSET(fd,11);
- return 0;
-}
-
-//---------------------------------------------------------
-// packet from map server
-
-int mapif_parse_LoadGuildStorage(int fd)
-{
- RFIFOHEAD(fd);
- mapif->load_guild_storage(fd,RFIFOL(fd,2),RFIFOL(fd,6),1);
- return 0;
-}
-
-int mapif_parse_SaveGuildStorage(int fd)
-{
- int guild_id;
- int len;
-
- RFIFOHEAD(fd);
- guild_id = RFIFOL(fd,8);
- len = RFIFOW(fd,2);
-
- if (sizeof(struct guild_storage) != len - 12) {
- ShowError("inter storage: data size mismatch: %d != %"PRIuS"\n", len - 12, sizeof(struct guild_storage));
- } else {
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id)) {
- Sql_ShowDebug(inter->sql_handle);
- } else if(SQL->NumRows(inter->sql_handle) > 0) {
- // guild exists
- SQL->FreeResult(inter->sql_handle);
- inter_storage->guild_storage_tosql(guild_id, RFIFOP(fd,12));
- mapif->save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 0);
- return 0;
- }
- SQL->FreeResult(inter->sql_handle);
- }
- mapif->save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 1);
- return 0;
-}
-
-int mapif_itembound_ack(int fd, int aid, int guild_id)
-{
-#ifdef GP_BOUND_ITEMS
- WFIFOHEAD(fd,8);
- WFIFOW(fd,0) = 0x3856;
- WFIFOL(fd,2) = aid;/* the value is not being used, drop? */
- WFIFOW(fd,6) = guild_id;
- WFIFOSET(fd,8);
-#endif
- return 0;
-}
-
//------------------------------------------------
//Guild bound items pull for offline characters [Akinari]
//Revised by [Mhalicot]
//------------------------------------------------
-int mapif_parse_ItemBoundRetrieve_sub(int fd)
+static bool inter_storage_retrieve_bound_items(int char_id, int account_id, int guild_id)
{
#ifdef GP_BOUND_ITEMS
StringBuf buf;
@@ -282,14 +352,13 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd)
int j, i=0, s=0, bound_qt=0;
struct item items[MAX_INVENTORY];
unsigned int bound_item[MAX_INVENTORY] = {0};
- int char_id = RFIFOL(fd,2);
- int aid = RFIFOL(fd,6);
- int guild_id = RFIFOW(fd,10);
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
- for( j = 0; j < MAX_SLOTS; ++j )
+ for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", `card%d`", j);
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j);
StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`='%d' AND `bound` = '%d'",inventory_db,char_id,IBT_GUILD);
stmt = SQL->StmtMalloc(inter->sql_handle);
@@ -299,34 +368,39 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd)
Sql_ShowDebug(inter->sql_handle);
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
- return 1;
+ return false;
}
memset(&item, 0, sizeof(item));
- SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &item.equip, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &item.bound, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, 0, NULL, NULL);
- for( j = 0; j < MAX_SLOTS; ++j )
- SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
-
- while( SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+ SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, sizeof item.id, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &item.nameid, sizeof item.nameid, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, sizeof item.amount, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &item.equip, sizeof item.equip, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &item.identify, sizeof item.identify, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &item.refine, sizeof item.refine, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, sizeof item.attribute, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, sizeof item.expire_time, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &item.bound, sizeof item.bound, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, sizeof item.unique_id, NULL, NULL);
+ /* Card Slots */
+ for (j = 0; j < MAX_SLOTS; ++j)
+ SQL->StmtBindColumn(stmt, 10 + j, SQLDT_INT, &item.card[j], sizeof item.card[j], NULL, NULL);
+ /* Item Options */
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j) {
+ SQL->StmtBindColumn(stmt, 10 + MAX_SLOTS + j * 2, SQLDT_INT16, &item.option[j].index, sizeof item.option[j].index, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 11 + MAX_SLOTS + j * 2, SQLDT_INT16, &item.option[j].value, sizeof item.option[j].value, NULL, NULL);
+ }
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
Assert_retb(i < MAX_INVENTORY);
memcpy(&items[i],&item,sizeof(struct item));
i++;
}
SQL->FreeResult(inter->sql_handle);
- if(!i) { //No items found - No need to continue
+ if (i == 0) { //No items found - No need to continue
StrBuf->Destroy(&buf);
SQL->StmtFree(stmt);
- return 0;
+ return true;
}
//First we delete the character's items
@@ -359,7 +433,7 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd)
Sql_ShowDebug(inter->sql_handle);
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
- return 1;
+ return false;
}
// Removes any view id that was set by an item that was removed
@@ -393,7 +467,7 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd)
Sql_ShowDebug(inter->sql_handle);
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
- return 1;
+ return false;
}
#undef CHECK_REMOVE
}
@@ -408,54 +482,47 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd)
StrBuf->Printf(&buf,"INSERT INTO `%s` (`guild_id`,`nameid`,`amount`,`equip`,`identify`,`refine`,"
"`attribute`,`expire_time`,`bound`,`unique_id`",
guild_storage_db);
- for( s = 0; s < MAX_SLOTS; ++s )
+ for (s = 0; s < MAX_SLOTS; ++s)
StrBuf->Printf(&buf, ", `card%d`", s);
+ for (s = 0; s < MAX_ITEM_OPTIONS; ++s)
+ StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", s, s);
StrBuf->AppendStr(&buf," ) VALUES ");
- for( j = 0; j < i; ++j ) {
- if( j )
+ for (j = 0; j < i; ++j) {
+ if (j != 0)
StrBuf->AppendStr(&buf, ",");
StrBuf->Printf(&buf, "('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'",
guild_id, items[j].nameid, items[j].amount, items[j].equip, items[j].identify, items[j].refine,
items[j].attribute, items[j].expire_time, items[j].bound, items[j].unique_id);
- for( s = 0; s < MAX_SLOTS; ++s )
+ for (s = 0; s < MAX_SLOTS; ++s)
StrBuf->Printf(&buf, ", '%d'", items[j].card[s]);
+ for (s = 0; s < MAX_ITEM_OPTIONS; ++s)
+ StrBuf->Printf(&buf, ", '%d', '%d'", items[j].option[s].index, items[j].option[s].value);
StrBuf->AppendStr(&buf, ")");
}
- if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
- || SQL_ERROR == SQL->StmtExecute(stmt) )
+ if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
+ || SQL_ERROR == SQL->StmtExecute(stmt))
{
Sql_ShowDebug(inter->sql_handle);
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
- return 1;
+ return false;
}
StrBuf->Destroy(&buf);
SQL->StmtFree(stmt);
-
- //Finally reload storage and tell map we're done
- mapif->load_guild_storage(fd,aid,guild_id,0);
-
- // If character is logged in char, disconnect
- chr->disconnect_player(aid);
#endif
- return 0;
-}
-
-void mapif_parse_ItemBoundRetrieve(int fd)
-{
- mapif->parse_ItemBoundRetrieve_sub(fd);
- /* tell map server the operation is over and it can unlock the storage */
- mapif->itembound_ack(fd,RFIFOL(fd,6),RFIFOW(fd,10));
+ return true;
}
-int inter_storage_parse_frommap(int fd)
+static int inter_storage_parse_frommap(int fd)
{
RFIFOHEAD(fd);
switch(RFIFOW(fd,0)){
+ case 0x3010: mapif->pAccountStorageLoad(fd); break;
+ case 0x3011: mapif->pAccountStorageSave(fd); break;
case 0x3018: mapif->parse_LoadGuildStorage(fd); break;
case 0x3019: mapif->parse_SaveGuildStorage(fd); break;
#ifdef GP_BOUND_ITEMS
@@ -480,4 +547,5 @@ void inter_storage_defaults(void)
inter_storage->delete_ = inter_storage_delete;
inter_storage->guild_storage_delete = inter_storage_guild_storage_delete;
inter_storage->parse_frommap = inter_storage_parse_frommap;
+ inter_storage->retrieve_bound_items = inter_storage_retrieve_bound_items;
}
diff --git a/src/char/int_storage.h b/src/char/int_storage.h
index 8c6341e85..918927620 100644
--- a/src/char/int_storage.h
+++ b/src/char/int_storage.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -21,6 +21,7 @@
#ifndef CHAR_INT_STORAGE_H
#define CHAR_INT_STORAGE_H
+#include "common/db.h"
#include "common/hercules.h"
struct storage_data;
@@ -30,15 +31,16 @@ struct guild_storage;
* inter_storage interface
**/
struct inter_storage_interface {
- int (*tosql) (int account_id, struct storage_data* p);
- int (*fromsql) (int account_id, struct storage_data* p);
- int (*guild_storage_tosql) (int guild_id, const struct guild_storage *p);
+ int (*tosql) (int account_id, const struct storage_data *p);
+ int (*fromsql) (int account_id, struct storage_data *p);
+ bool (*guild_storage_tosql) (int guild_id, const struct guild_storage *p);
int (*guild_storage_fromsql) (int guild_id, struct guild_storage* p);
int (*sql_init) (void);
void (*sql_final) (void);
int (*delete_) (int account_id);
int (*guild_storage_delete) (int guild_id);
int (*parse_frommap) (int fd);
+ bool (*retrieve_bound_items) (int char_id, int account_id, int guild_id);
};
#ifdef HERCULES_CORE
diff --git a/src/char/inter.c b/src/char/inter.c
index d076bb657..418c9b0a1 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -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"
@@ -33,7 +34,9 @@
#include "char/int_party.h"
#include "char/int_pet.h"
#include "char/int_quest.h"
+#include "char/int_rodex.h"
#include "char/int_storage.h"
+#include "char/int_achievement.h"
#include "char/mapif.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
@@ -53,44 +56,40 @@
#define WISDATA_TTL (60*1000) // Wis data Time To Live (60 seconds)
#define WISDELLIST_MAX 256 // Number of elements in the list Delete data Wis
-struct inter_interface inter_s;
+static struct inter_interface inter_s;
struct inter_interface *inter;
-int char_server_port = 3306;
-char char_server_ip[32] = "127.0.0.1";
-char char_server_id[32] = "ragnarok";
-char char_server_pw[100] = "ragnarok";
-char char_server_db[32] = "ragnarok";
-char default_codepage[32] = ""; //Feature by irmin.
+static int char_server_port = 3306;
+static char char_server_ip[32] = "127.0.0.1";
+static char char_server_id[32] = "ragnarok";
+static char char_server_pw[100] = "ragnarok";
+static char char_server_db[32] = "ragnarok";
+static char default_codepage[32] = ""; //Feature by irmin.
int party_share_level = 10;
// recv. packet list
-int inter_recv_packet_length[] = {
+static int inter_recv_packet_length[] = {
-1,-1, 7,-1, -1,13,36, (2 + 4 + 4 + 4 + NAME_LENGTH), 0, 0, 0, 0, 0, 0, 0, 0, // 3000-
- 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010-
+ 6,-1, 6,-1, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010- Account Storage, Achievements [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]
- 48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3080-
- -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
+ 52,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3080-
+ -1,10,-1, 6, 0, 20,10,11, -1,6 + NAME_LENGTH, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator], RoDEX packets
};
-struct WisData {
- int id, fd, count, len;
- int64 tick;
- unsigned char src[24], dst[24], msg[512];
-};
static struct DBMap *wis_db = NULL; // int wis_id -> struct WisData*
static int wis_dellist[WISDELLIST_MAX], wis_delnum;
#define MAX_JOB_NAMES 150
-static char* msg_table[MAX_JOB_NAMES]; // messages 550 ~ 699 are job names
+static char *msg_table[MAX_JOB_NAMES]; // messages 550 ~ 699 are job names
-const char* inter_msg_txt(int msg_number) {
+static const char *inter_msg_txt(int msg_number)
+{
msg_number -= 550;
if (msg_number >= 0 && msg_number < MAX_JOB_NAMES &&
msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0')
@@ -109,7 +108,7 @@ const char* inter_msg_txt(int msg_number) {
* @param[in] allow_override whether to allow duplicate message IDs to override the original value.
* @return success state.
*/
-bool inter_msg_config_read(const char *cfg_name, bool allow_override)
+static bool inter_msg_config_read(const char *cfg_name, bool allow_override)
{
int msg_number;
char line[1024], w1[1024], w2[1024];
@@ -161,14 +160,14 @@ bool inter_msg_config_read(const char *cfg_name, bool allow_override)
/*==========================================
* Cleanup Message Data
*------------------------------------------*/
-void inter_do_final_msg(void)
+static void inter_do_final_msg(void)
{
int i;
for (i = 0; i < MAX_JOB_NAMES; i++)
aFree(msg_table[i]);
}
/* from pc.c due to @accinfo. any ideas to replace this crap are more than welcome. */
-const char* inter_job_name(int class)
+static const char *inter_job_name(int class)
{
switch (class) {
case JOB_NOVICE: // 550
@@ -401,7 +400,7 @@ const char* inter_job_name(int class)
* Argument-list version of inter_msg_to_fd
* @see inter_msg_to_fd
*/
-void inter_vmsg_to_fd(int fd, int u_fd, int aid, char* msg, va_list ap)
+static void inter_vmsg_to_fd(int fd, int u_fd, int aid, char *msg, va_list ap)
{
char msg_out[512];
va_list apcopy;
@@ -434,8 +433,8 @@ void inter_vmsg_to_fd(int fd, int u_fd, int aid, char* msg, va_list ap)
* @param msg Message format string
* @param ... Additional parameters for (v)sprinf
*/
-void inter_msg_to_fd(int fd, int u_fd, int aid, char *msg, ...) __attribute__((format(printf, 4, 5)));
-void inter_msg_to_fd(int fd, int u_fd, int aid, char *msg, ...)
+static void inter_msg_to_fd(int fd, int u_fd, int aid, char *msg, ...) __attribute__((format(printf, 4, 5)));
+static void inter_msg_to_fd(int fd, int u_fd, int aid, char *msg, ...)
{
va_list ap;
va_start(ap,msg);
@@ -444,15 +443,12 @@ void inter_msg_to_fd(int fd, int u_fd, int aid, char *msg, ...)
}
/* [Dekamaster/Nightroad] */
-void mapif_parse_accinfo(int fd)
+static void inter_accinfo(int u_fd, int aid, int castergroup, const char *query, int map_fd)
{
- int u_fd = RFIFOL(fd,2), aid = RFIFOL(fd,6), castergroup = RFIFOL(fd,10);
- char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1];
+ char query_esq[NAME_LENGTH*2+1];
int account_id;
char *data;
- safestrncpy(query, RFIFOP(fd,14), NAME_LENGTH);
-
SQL->EscapeString(inter->sql_handle, query_esq, query);
account_id = atoi(query);
@@ -462,10 +458,10 @@ void mapif_parse_accinfo(int fd)
if ( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", char_db, query_esq)
|| SQL->NumRows(inter->sql_handle) == 0 ) {
if( SQL->NumRows(inter->sql_handle) == 0 ) {
- inter->msg_to_fd(fd, u_fd, aid, "No matches were found for your criteria, '%s'",query);
+ inter->msg_to_fd(map_fd, u_fd, aid, "No matches were found for your criteria, '%s'",query);
} else {
Sql_ShowDebug(inter->sql_handle);
- inter->msg_to_fd(fd, u_fd, aid, "An error occurred, bother your admin about it.");
+ inter->msg_to_fd(map_fd, u_fd, aid, "An error occurred, bother your admin about it.");
}
SQL->FreeResult(inter->sql_handle);
return;
@@ -475,7 +471,7 @@ void mapif_parse_accinfo(int fd)
SQL->GetData(inter->sql_handle, 0, &data, NULL); account_id = atoi(data);
SQL->FreeResult(inter->sql_handle);
} else {// more than one, listing... [Dekamaster/Nightroad]
- inter->msg_to_fd(fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)SQL->NumRows(inter->sql_handle));
+ inter->msg_to_fd(map_fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)SQL->NumRows(inter->sql_handle));
while ( SQL_SUCCESS == SQL->NextRow(inter->sql_handle) ) {
int class;
int base_level, job_level, online;
@@ -488,7 +484,7 @@ void mapif_parse_accinfo(int fd)
SQL->GetData(inter->sql_handle, 4, &data, NULL); job_level = atoi(data);
SQL->GetData(inter->sql_handle, 5, &data, NULL); online = atoi(data);
- inter->msg_to_fd(fd, u_fd, aid, "[AID: %d] %s | %s | Level: %d/%d | %s", account_id, name, inter->job_name(class), base_level, job_level, online?"Online":"Offline");
+ inter->msg_to_fd(map_fd, u_fd, aid, "[AID: %d] %s | %s | Level: %d/%d | %s", account_id, name, inter->job_name(class), base_level, job_level, online?"Online":"Offline");
}
SQL->FreeResult(inter->sql_handle);
return;
@@ -499,12 +495,13 @@ void mapif_parse_accinfo(int fd)
/* it will only get here if we have a single match */
/* and we will send packet with account id to login server asking for account info */
if( account_id ) {
- mapif->on_parse_accinfo(account_id, u_fd, aid, castergroup, fd);
+ mapif->on_parse_accinfo(account_id, u_fd, aid, castergroup, map_fd);
}
return;
}
-void mapif_parse_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass,
+
+static void inter_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass,
const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate,
int group_id, int logincount, int state)
{
@@ -525,12 +522,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)));
@@ -574,7 +574,7 @@ void mapif_parse_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int acc
* @param val either str or int, depending on type
* @param type false when int, true otherwise
**/
-void inter_savereg(int account_id, int char_id, const char *key, unsigned int index, intptr_t val, bool is_string)
+static void inter_savereg(int account_id, int char_id, const char *key, unsigned int index, intptr_t val, bool is_string)
{
char val_esq[1000];
nullpo_retv(key);
@@ -627,7 +627,7 @@ void inter_savereg(int account_id, int char_id, const char *key, unsigned int in
}
// Load account_reg from sql (type=2)
-int inter_accreg_fromsql(int account_id,int char_id, int fd, int type)
+static int inter_accreg_fromsql(int account_id, int char_id, int fd, int type)
{
char* data;
size_t len;
@@ -804,7 +804,7 @@ int inter_accreg_fromsql(int account_id,int char_id, int fd, int type)
*
* @retval false in case of error.
*/
-bool inter_config_read_log(const char *filename, const struct config_t *config, bool imported)
+static bool inter_config_read_log(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -832,7 +832,7 @@ bool inter_config_read_log(const char *filename, const struct config_t *config,
*
* @retval false in case of error.
*/
-bool inter_config_read_connection(const char *filename, const struct config_t *config, bool imported)
+static bool inter_config_read_connection(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
@@ -865,7 +865,7 @@ bool inter_config_read_connection(const char *filename, const struct config_t *c
*
* @retval false in case of error.
*/
-bool inter_config_read(const char *filename, bool imported)
+static bool inter_config_read(const char *filename, bool imported)
{
struct config_t config;
const struct config_setting_t *setting = NULL;
@@ -909,7 +909,7 @@ bool inter_config_read(const char *filename, bool imported)
* Save interlog into sql (arglist version)
* @see inter_log
*/
-int inter_vlog(char* fmt, va_list ap)
+static int inter_vlog(char *fmt, va_list ap)
{
char str[255];
char esc_str[sizeof(str)*2+1];// escaped str
@@ -932,7 +932,7 @@ int inter_vlog(char* fmt, va_list ap)
* @param ... Additional (printf-like) arguments
* @return Always 0 // FIXME
*/
-int inter_log(char* fmt, ...)
+static int inter_log(char *fmt, ...)
{
va_list ap;
int ret;
@@ -945,7 +945,7 @@ int inter_log(char* fmt, ...)
}
// initialize
-int inter_init_sql(const char *file)
+static int inter_init_sql(const char *file)
{
inter->config_read(file, false);
@@ -974,6 +974,8 @@ int inter_init_sql(const char *file)
inter_elemental->sql_init();
inter_mail->sql_init();
inter_auction->sql_init();
+ inter_rodex->sql_init();
+ inter_achievement->sql_init();
geoip->init();
inter->msg_config_read("conf/messages.conf", false);
@@ -981,7 +983,7 @@ int inter_init_sql(const char *file)
}
// finalize
-void inter_final(void)
+static void inter_final(void)
{
wis_db->destroy(wis_db, NULL);
@@ -994,120 +996,26 @@ void inter_final(void)
inter_elemental->sql_final();
inter_mail->sql_final();
inter_auction->sql_final();
+ inter_rodex->sql_final();
+ inter_achievement->sql_final();
geoip->final(true);
inter->do_final_msg();
return;
}
-int inter_mapif_init(int fd)
-{
- return 0;
-}
-
-
-//--------------------------------------------------------
-
-// broadcast sending
-int mapif_broadcast(const unsigned char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd)
-{
- unsigned char *buf = (unsigned char*)aMalloc((len)*sizeof(unsigned char));
-
- nullpo_ret(mes);
- Assert_ret(len >= 16);
- WBUFW(buf,0) = 0x3800;
- WBUFW(buf,2) = len;
- WBUFL(buf,4) = fontColor;
- WBUFW(buf,8) = fontType;
- WBUFW(buf,10) = fontSize;
- WBUFW(buf,12) = fontAlign;
- WBUFW(buf,14) = fontY;
- memcpy(WBUFP(buf,16), mes, len - 16);
- mapif->sendallwos(sfd, buf, len);
-
- aFree(buf);
- return 0;
-}
-
-// Wis sending
-int mapif_wis_message(struct WisData *wd)
-{
- unsigned char buf[2048];
- nullpo_ret(wd);
- //if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex]
- if (wd->len < 0)
- wd->len = 0;
- if (wd->len >= (int)sizeof(wd->msg) - 1)
- wd->len = (int)sizeof(wd->msg) - 1;
-
- WBUFW(buf, 0) = 0x3801;
- WBUFW(buf, 2) = 56 +wd->len;
- WBUFL(buf, 4) = wd->id;
- memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH);
- memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH);
- memcpy(WBUFP(buf,56), wd->msg, wd->len);
- wd->count = mapif->sendall(buf,WBUFW(buf,2));
-
- return 0;
-}
-
-void mapif_wis_response(int fd, const unsigned char *src, int flag)
-{
- unsigned char buf[27];
- nullpo_retv(src);
- WBUFW(buf, 0)=0x3802;
- memcpy(WBUFP(buf, 2),src,24);
- WBUFB(buf,26)=flag;
- mapif->send(fd,buf,27);
-}
-
-// Wis sending result
-int mapif_wis_end(struct WisData *wd, int flag)
+static int inter_mapif_init(int fd)
{
- nullpo_ret(wd);
- mapif->wis_response(wd->fd, wd->src, flag);
return 0;
}
-#if 0
-// Account registry transfer to map-server
-static void mapif_account_reg(int fd, unsigned char *src)
-{
- nullpo_retv(src);
- WBUFW(src,0)=0x3804; //NOTE: writing to RFIFO
- mapif->sendallwos(fd, src, WBUFW(src,2));
-}
-#endif // 0
-
-// Send the requested account_reg
-int mapif_account_reg_reply(int fd,int account_id,int char_id, int type)
-{
- inter->accreg_fromsql(account_id,char_id,fd,type);
- return 0;
-}
-
-//Request to kick char from a certain map server. [Skotlex]
-int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason)
-{
- if (fd >= 0)
- {
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x2b1f;
- WFIFOL(fd,2) = account_id;
- WFIFOB(fd,6) = reason;
- WFIFOSET(fd,7);
- return 0;
- }
- return -1;
-}
-
//--------------------------------------------------------
/**
* Existence check of WISP data
* @see DBApply
*/
-int inter_check_ttl_wisdata_sub(union DBKey key, struct DBData *data, va_list ap)
+static int inter_check_ttl_wisdata_sub(union DBKey key, struct DBData *data, va_list ap)
{
int64 tick;
struct WisData *wd = DB->data2ptr(data);
@@ -1120,7 +1028,7 @@ int inter_check_ttl_wisdata_sub(union DBKey key, struct DBData *data, va_list ap
return 0;
}
-int inter_check_ttl_wisdata(void)
+static int inter_check_ttl_wisdata(void)
{
int64 tick = timer->gettick();
int i;
@@ -1140,225 +1048,36 @@ int inter_check_ttl_wisdata(void)
return 0;
}
-//--------------------------------------------------------
-
-// broadcast sending
-int mapif_parse_broadcast(int fd)
-{
- mapif->broadcast(RFIFOP(fd,16), RFIFOW(fd,2), RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), fd);
- return 0;
-}
-
-
-// Wisp/page request to send
-int mapif_parse_WisRequest(int fd)
-{
- struct WisData* wd;
- char name[NAME_LENGTH];
- char esc_name[NAME_LENGTH*2+1];// escaped name
- char* data;
- size_t len;
-
-
- if ( fd <= 0 ) {return 0;} // check if we have a valid fd
-
- if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
- ShowWarning("inter: Wis message size too long.\n");
- return 0;
- } else if (RFIFOW(fd,2)-52 <= 0) { // normally, impossible, but who knows...
- ShowError("inter: Wis message doesn't exist.\n");
- return 0;
- }
-
- safestrncpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
-
- SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) )
- Sql_ShowDebug(inter->sql_handle);
-
- // search if character exists before to ask all map-servers
- if( SQL_SUCCESS != SQL->NextRow(inter->sql_handle) )
- {
- mapif->wis_response(fd, RFIFOP(fd, 4), 1);
- }
- else
- {// Character exists. So, ask all map-servers
- // to be sure of the correct name, rewrite it
- SQL->GetData(inter->sql_handle, 0, &data, &len);
- memset(name, 0, NAME_LENGTH);
- memcpy(name, data, min(len, NAME_LENGTH));
- // if source is destination, don't ask other servers.
- if (strncmp(RFIFOP(fd,4), name, NAME_LENGTH) == 0) {
- mapif->wis_response(fd, RFIFOP(fd, 4), 1);
- }
- else
- {
- static int wisid = 0;
- CREATE(wd, struct WisData, 1);
-
- // Whether the failure of previous wisp/page transmission (timeout)
- inter->check_ttl_wisdata();
-
- wd->id = ++wisid;
- wd->fd = fd;
- wd->len= RFIFOW(fd,2)-52;
- memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH);
- memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH);
- memcpy(wd->msg, RFIFOP(fd,52), wd->len);
- wd->tick = timer->gettick();
- idb_put(wis_db, wd->id, wd);
- mapif->wis_message(wd);
- }
- }
-
- SQL->FreeResult(inter->sql_handle);
- return 0;
-}
-
-
-// Wisp/page transmission result
-int mapif_parse_WisReply(int fd)
+static struct WisData *inter_add_wisdata(int fd, const unsigned char *src, const unsigned char *dst, const unsigned char *msg, int msg_len)
{
- int id, flag;
+ static int wisid = 0;
struct WisData *wd;
- id = RFIFOL(fd,2);
- flag = RFIFOB(fd,6);
- wd = (struct WisData*)idb_get(wis_db, id);
- if (wd == NULL)
- return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
-
- if ((--wd->count) <= 0 || flag != 1) {
- mapif->wis_end(wd, flag); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target
- idb_remove(wis_db, id);
- }
-
- return 0;
-}
-
-// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
-int mapif_parse_WisToGM(int fd)
-{
- unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
+ CREATE(wd, struct WisData, 1);
- memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); // Message contains the NUL terminator (see intif_wis_message_to_gm())
- WBUFW(buf, 0) = 0x3803;
- mapif->sendall(buf, RFIFOW(fd,2));
+ // Whether the failure of previous wisp/page transmission (timeout)
+ inter->check_ttl_wisdata();
- return 0;
-}
-
-// Save account_reg into sql (type=2)
-int mapif_parse_Registry(int fd)
-{
- int account_id = RFIFOL(fd, 4), char_id = RFIFOL(fd, 8), count = RFIFOW(fd, 12);
-
- if( count ) {
- int cursor = 14, i;
- char key[SCRIPT_VARNAME_LENGTH+1], sval[254];
- bool isLoginActive = sockt->session_is_active(chr->login_fd);
-
- if( isLoginActive )
- chr->global_accreg_to_login_start(account_id,char_id);
-
- for(i = 0; i < count; i++) {
- unsigned int index;
- int len = RFIFOB(fd, cursor);
- safestrncpy(key, RFIFOP(fd, cursor + 1), min((int)sizeof(key), len));
- cursor += len + 1;
-
- index = RFIFOL(fd, cursor);
- cursor += 4;
-
- switch (RFIFOB(fd, cursor++)) {
- /* int */
- case 0:
- inter->savereg(account_id,char_id,key,index,RFIFOL(fd, cursor),false);
- cursor += 4;
- break;
- case 1:
- inter->savereg(account_id,char_id,key,index,0,false);
- break;
- /* str */
- case 2:
- len = RFIFOB(fd, cursor);
- safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len));
- cursor += len + 1;
- inter->savereg(account_id,char_id,key,index,(intptr_t)sval,true);
- break;
- case 3:
- inter->savereg(account_id,char_id,key,index,0,true);
- break;
- default:
- ShowError("mapif->parse_Registry: unknown type %d\n",RFIFOB(fd, cursor - 1));
- return 1;
- }
-
- }
-
- if (isLoginActive)
- chr->global_accreg_to_login_send();
- }
- return 0;
-}
+ wd->id = ++wisid;
+ wd->fd = fd;
+ wd->len = msg_len;
+ memcpy(wd->src, src, NAME_LENGTH);
+ memcpy(wd->dst, dst, NAME_LENGTH);
+ memcpy(wd->msg, msg, wd->len);
+ wd->tick = timer->gettick();
+ idb_put(wis_db, wd->id, wd);
-// Request the value of all registries.
-int mapif_parse_RegistryRequest(int fd)
-{
- //Load Char Registry
- if (RFIFOB(fd,12)) mapif->account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),3); // 3: char reg
- //Load Account Registry
- if (RFIFOB(fd,11)) mapif->account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2); // 2: account reg
- //Ask Login Server for Account2 values.
- if (RFIFOB(fd,10)) chr->request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6));
- return 1;
+ return wd;
}
-void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, const char *const name)
+static struct WisData *inter_get_wisdata(int id)
{
- nullpo_retv(name);
- WFIFOHEAD(fd, NAME_LENGTH+13);
- WFIFOW(fd, 0) = 0x3806;
- WFIFOL(fd, 2) = account_id;
- WFIFOL(fd, 6) = char_id;
- WFIFOB(fd,10) = type;
- WFIFOB(fd,11) = flag;
- memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
- WFIFOSET(fd, NAME_LENGTH+13);
+ return idb_get(wis_db, id);
}
-int mapif_parse_NameChangeRequest(int fd)
+static void inter_remove_wisdata(int id)
{
- int account_id, char_id, type;
- const char *name;
- int i;
-
- account_id = RFIFOL(fd,2);
- char_id = RFIFOL(fd,6);
- type = RFIFOB(fd,10);
- name = RFIFOP(fd,11);
-
- // Check Authorized letters/symbols in the name
- if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorized
- for (i = 0; i < NAME_LENGTH && name[i]; i++)
- if (strchr(char_name_letters, name[i]) == NULL) {
- mapif->namechange_ack(fd, account_id, char_id, type, 0, name);
- return 0;
- }
- } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
- for (i = 0; i < NAME_LENGTH && name[i]; i++)
- if (strchr(char_name_letters, name[i]) != NULL) {
- mapif->namechange_ack(fd, account_id, char_id, type, 0, name);
- return 0;
- }
- }
- //TODO: type holds the type of object to rename.
- //If it were a player, it needs to have the guild information and db information
- //updated here, because changing it on the map won't make it be saved [Skotlex]
-
- //name allowed.
- mapif->namechange_ack(fd, account_id, char_id, type, 1, name);
- return 0;
+ idb_remove(wis_db, id);
}
//--------------------------------------------------------
@@ -1367,7 +1086,7 @@ int mapif_parse_NameChangeRequest(int fd)
/// or 0 if no complete packet exists in the queue.
///
/// @param length The minimum allowed length, or -1 for dynamic lookup
-int inter_check_length(int fd, int length)
+static int inter_check_length(int fd, int length)
{
if( length == -1 )
{// variable-length packet
@@ -1382,7 +1101,7 @@ int inter_check_length(int fd, int length)
return length;
}
-int inter_parse_frommap(int fd)
+static int inter_parse_frommap(int fd)
{
int cmd;
int len = 0;
@@ -1404,7 +1123,6 @@ int inter_parse_frommap(int fd)
case 0x3005: mapif->parse_RegistryRequest(fd); break;
case 0x3006: mapif->parse_NameChangeRequest(fd); break;
case 0x3007: mapif->parse_accinfo(fd); break;
- /* 0x3008 is used by the report stuff */
default:
if( inter_party->parse_frommap(fd)
|| inter_guild->parse_frommap(fd)
@@ -1416,6 +1134,9 @@ int inter_parse_frommap(int fd)
|| inter_mail->parse_frommap(fd)
|| inter_auction->parse_frommap(fd)
|| inter_quest->parse_frommap(fd)
+ || inter_rodex->parse_frommap(fd)
+ || inter_clan->parse_frommap(fd)
+ || inter_achievement->parse_frommap(fd)
)
break;
else
@@ -1453,4 +1174,9 @@ void inter_defaults(void)
inter->final = inter_final;
inter->config_read_log = inter_config_read_log;
inter->config_read_connection = inter_config_read_connection;
+ inter->accinfo = inter_accinfo;
+ inter->accinfo2 = inter_accinfo2;
+ inter->add_wisdata = inter_add_wisdata;
+ inter->get_wisdata = inter_get_wisdata;
+ inter->remove_wisdata = inter_remove_wisdata;
}
diff --git a/src/char/inter.h b/src/char/inter.h
index 796f89a96..94ee3ab60 100644
--- a/src/char/inter.h
+++ b/src/char/inter.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -30,6 +30,12 @@
struct Sql; // common/sql.h
struct config_t; // common/conf.h
+struct WisData {
+ int id, fd, count, len;
+ int64 tick;
+ unsigned char src[24], dst[24], msg[512];
+};
+
/**
* inter interface
**/
@@ -56,6 +62,13 @@ struct inter_interface {
bool (*config_read) (const char *filename, bool imported);
bool (*config_read_log) (const char *filename, const struct config_t *config, bool imported);
bool (*config_read_connection) (const char *filename, const struct config_t *config, bool imported);
+ void (*accinfo) (int u_fd, int aid, int castergroup, const char *query, int map_fd);
+ void (*accinfo2) (bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass,
+ const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate,
+ int group_id, int logincount, int state);
+ struct WisData *(*add_wisdata) (int fd, const unsigned char *src, const unsigned char *dst, const unsigned char *msg, int msg_len);
+ struct WisData *(*get_wisdata) (int id);
+ void (*remove_wisdata) (int id);
};
#ifdef HERCULES_CORE
diff --git a/src/char/loginif.c b/src/char/loginif.c
index b0e18eb1f..a093c8cf5 100644
--- a/src/char/loginif.c
+++ b/src/char/loginif.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -35,12 +35,12 @@
#include <stdlib.h>
#include <string.h>
-struct loginif_interface loginif_s;
+static struct loginif_interface loginif_s;
struct loginif_interface *loginif;
/// Resets all the data.
-void loginif_reset(void) __attribute__ ((noreturn));
-void loginif_reset(void)
+static void loginif_reset(void) __attribute__ ((noreturn));
+static void loginif_reset(void)
{
int id;
// TODO kick everyone out and reset everything or wait for connect and try to reacquire locks [FlavioJS]
@@ -54,7 +54,7 @@ void loginif_reset(void)
/// Checks the conditions for the server to stop.
/// Releases the cookie when all characters are saved.
/// If all the conditions are met, it stops the core loop.
-void loginif_check_shutdown(void)
+static void loginif_check_shutdown(void)
{
if( core->runflag != CHARSERVER_ST_SHUTDOWN )
return;
@@ -63,14 +63,14 @@ void loginif_check_shutdown(void)
/// Called when the connection to Login Server is disconnected.
-void loginif_on_disconnect(void)
+static void loginif_on_disconnect(void)
{
ShowWarning("Connection to Login Server lost.\n\n");
}
/// Called when all the connection steps are completed.
-void loginif_on_ready(void)
+static void loginif_on_ready(void)
{
int i;
@@ -85,7 +85,7 @@ void loginif_on_ready(void)
ShowStatus("Awaiting maps from map-server.\n");
}
-void do_init_loginif(void)
+static void do_init_loginif(void)
{
// establish char-login connection if not present
timer->add_func_list(chr->check_connect_login_server, "chr->check_connect_login_server");
@@ -96,7 +96,7 @@ void do_init_loginif(void)
timer->add_interval(timer->gettick() + 1000, chr->send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
}
-void do_final_loginif(void)
+static void do_final_loginif(void)
{
if (chr->login_fd != -1) {
sockt->close(chr->login_fd);
@@ -104,7 +104,7 @@ void do_final_loginif(void)
}
}
-void loginif_block_account(int account_id, int flag)
+static void loginif_block_account(int account_id, int flag)
{
Assert_retv(chr->login_fd != -1);
WFIFOHEAD(chr->login_fd,10);
@@ -114,7 +114,7 @@ void loginif_block_account(int account_id, int flag)
WFIFOSET(chr->login_fd,10);
}
-void loginif_ban_account(int account_id, short year, short month, short day, short hour, short minute, short second)
+static void loginif_ban_account(int account_id, short year, short month, short day, short hour, short minute, short second)
{
Assert_retv(chr->login_fd != -1);
WFIFOHEAD(chr->login_fd,18);
@@ -129,7 +129,7 @@ void loginif_ban_account(int account_id, short year, short month, short day, sho
WFIFOSET(chr->login_fd,18);
}
-void loginif_unban_account(int account_id)
+static void loginif_unban_account(int account_id)
{
Assert_retv(chr->login_fd != -1);
WFIFOHEAD(chr->login_fd,6);
@@ -138,7 +138,7 @@ void loginif_unban_account(int account_id)
WFIFOSET(chr->login_fd,6);
}
-void loginif_changesex(int account_id)
+static void loginif_changesex(int account_id)
{
Assert_retv(chr->login_fd != -1);
WFIFOHEAD(chr->login_fd,6);
@@ -147,7 +147,7 @@ void loginif_changesex(int account_id)
WFIFOSET(chr->login_fd,6);
}
-void loginif_auth(int fd, struct char_session_data* sd, uint32 ipl)
+static void loginif_auth(int fd, struct char_session_data *sd, uint32 ipl)
{
Assert_retv(chr->login_fd != -1);
nullpo_retv(sd);
@@ -162,7 +162,7 @@ void loginif_auth(int fd, struct char_session_data* sd, uint32 ipl)
WFIFOSET(chr->login_fd,23);
}
-void loginif_send_users_count(int users)
+static void loginif_send_users_count(int users)
{
Assert_retv(chr->login_fd != -1);
WFIFOHEAD(chr->login_fd,6);
@@ -171,7 +171,7 @@ void loginif_send_users_count(int users)
WFIFOSET(chr->login_fd,6);
}
-void loginif_connect_to_server(void)
+static void loginif_connect_to_server(void)
{
Assert_retv(chr->login_fd != -1);
WFIFOHEAD(chr->login_fd,86);
diff --git a/src/char/loginif.h b/src/char/loginif.h
index daafdf4ac..5dfedb952 100644
--- a/src/char/loginif.h
+++ b/src/char/loginif.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
diff --git a/src/char/mapif.c b/src/char/mapif.c
index 1dafb79c3..dc5735550 100644
--- a/src/char/mapif.c
+++ b/src/char/mapif.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -20,197 +20,2449 @@
*/
#define HERCULES_CORE
+#include "config/core.h" // GP_BOUND_ITEMS
#include "mapif.h"
#include "char/char.h"
+#include "char/int_achievement.h"
#include "char/int_auction.h"
+#include "char/int_clan.h"
#include "char/int_guild.h"
#include "char/int_homun.h"
+#include "char/int_elemental.h"
+#include "char/int_mail.h"
+#include "char/int_mercenary.h"
+#include "char/int_party.h"
+#include "char/int_pet.h"
+#include "char/int_quest.h"
+#include "char/int_rodex.h"
+#include "char/int_storage.h"
+#include "char/inter.h"
#include "common/cbasetypes.h"
+#include "common/memmgr.h"
#include "common/mmo.h"
+#include "common/nullpo.h"
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h"
+#include "common/sql.h"
#include "common/strlib.h"
#include <stdlib.h>
-void mapif_ban(int id, unsigned int flag, int status);
-void mapif_server_init(int id);
-void mapif_server_destroy(int id);
-void mapif_server_reset(int id);
-void mapif_on_disconnect(int id);
-void mapif_on_parse_accinfo(int account_id, int u_fd, int u_aid, int u_group, int map_fd);
-void mapif_char_ban(int char_id, time_t timestamp);
-int mapif_sendall(const unsigned char *buf, unsigned int len);
-int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len);
-int mapif_send(int fd, unsigned char *buf, unsigned int len);
-void mapif_send_users_count(int users);
-void mapif_auction_message(int char_id, unsigned char result);
-void mapif_auction_sendlist(int fd, int char_id, short count, short pages, unsigned char *buf);
-void mapif_parse_auction_requestlist(int fd);
-void mapif_auction_register(int fd, struct auction_data *auction);
-void mapif_parse_auction_register(int fd);
-void mapif_auction_cancel(int fd, int char_id, unsigned char result);
-void mapif_parse_auction_cancel(int fd);
-void mapif_auction_close(int fd, int char_id, unsigned char result);
-void mapif_parse_auction_close(int fd);
-void mapif_auction_bid(int fd, int char_id, int bid, unsigned char result);
-void mapif_parse_auction_bid(int fd);
-bool mapif_elemental_create(struct s_elemental *ele);
-bool mapif_elemental_save(const struct s_elemental *ele);
-bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele);
-bool mapif_elemental_delete(int ele_id);
-void mapif_elemental_send(int fd, struct s_elemental *ele, unsigned char flag);
-void mapif_parse_elemental_create(int fd, const struct s_elemental *ele);
-void mapif_parse_elemental_load(int fd, int ele_id, int char_id);
-void mapif_elemental_deleted(int fd, unsigned char flag);
-void mapif_parse_elemental_delete(int fd, int ele_id);
-void mapif_elemental_saved(int fd, unsigned char flag);
-void mapif_parse_elemental_save(int fd, const struct s_elemental *ele);
-int mapif_guild_created(int fd, int account_id, struct guild *g);
-int mapif_guild_noinfo(int fd, int guild_id);
-int mapif_guild_info(int fd, struct guild *g);
-int mapif_guild_memberadded(int fd, int guild_id, int account_id, int char_id, int flag);
-int mapif_guild_withdraw(int guild_id, int account_id, int char_id, int flag, const char *name, const char *mes);
-int mapif_guild_memberinfoshort(struct guild *g, int idx);
-int mapif_guild_broken(int guild_id, int flag);
-int mapif_guild_message(int guild_id, int account_id, const char *mes, int len, int sfd);
-int mapif_guild_basicinfochanged(int guild_id, int type, const void *data, int len);
-int mapif_guild_memberinfochanged(int guild_id, int account_id, int char_id, int type, const void *data, int len);
-int mapif_guild_skillupack(int guild_id, uint16 skill_id, int account_id);
-int mapif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag, const char *name1, const char *name2);
-int mapif_guild_position(struct guild *g, int idx);
-int mapif_guild_notice(struct guild *g);
-int mapif_guild_emblem(struct guild *g);
-int mapif_guild_master_changed(struct guild *g, int aid, int cid);
-int mapif_guild_castle_dataload(int fd, int sz, const int *castle_ids);
-int mapif_parse_CreateGuild(int fd, int account_id, const char *name, const struct guild_member *master);
-int mapif_parse_GuildInfo(int fd, int guild_id);
-int mapif_parse_GuildAddMember(int fd, int guild_id, const struct guild_member *m);
-int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes);
-int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id, int char_id, int online, int lv, int16 class);
-int mapif_parse_BreakGuild(int fd, int guild_id);
-int mapif_parse_GuildMessage(int fd, int guild_id, int account_id, const char *mes, int len);
-int mapif_parse_GuildBasicInfoChange(int fd, int guild_id, int type, const void *data, int len);
-int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int char_id, int type, const char *data, int len);
-int mapif_parse_GuildPosition(int fd, int guild_id, int idx, const struct guild_position *p);
-int mapif_parse_GuildSkillUp(int fd, int guild_id, uint16 skill_id, int account_id, int max);
-int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, int account_id1, int account_id2, int flag);
-int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_id1, int account_id2, int flag);
-int mapif_parse_GuildNotice(int fd, int guild_id, const char *mes1, const char *mes2);
-int mapif_parse_GuildEmblem(int fd, int len, int guild_id, int dummy, const char *data);
-int mapif_parse_GuildCastleDataLoad(int fd, int len, const int *castle_ids);
-int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value);
-int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int len);
-void mapif_homunculus_created(int fd, int account_id, const struct s_homunculus *sh, unsigned char flag);
-void mapif_homunculus_deleted(int fd, int flag);
-void mapif_homunculus_loaded(int fd, int account_id, struct s_homunculus *hd);
-void mapif_homunculus_saved(int fd, int account_id, bool flag);
-void mapif_homunculus_renamed(int fd, int account_id, int char_id, unsigned char flag, const char *name);
-bool mapif_homunculus_create(struct s_homunculus *hd);
-bool mapif_homunculus_save(const struct s_homunculus *hd);
-bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd);
-bool mapif_homunculus_delete(int homun_id);
-bool mapif_homunculus_rename(const char *name);
-void mapif_parse_homunculus_create(int fd, int len, int account_id, const struct s_homunculus *phd);
-void mapif_parse_homunculus_delete(int fd, int homun_id);
-void mapif_parse_homunculus_load(int fd, int account_id, int homun_id);
-void mapif_parse_homunculus_save(int fd, int len, int account_id, const struct s_homunculus *phd);
-void mapif_parse_homunculus_rename(int fd, int account_id, int char_id, const char *name);
-void mapif_mail_sendinbox(int fd, int char_id, unsigned char flag, struct mail_data *md);
-void mapif_parse_mail_requestinbox(int fd);
-void mapif_parse_mail_read(int fd);
-void mapif_mail_sendattach(int fd, int char_id, struct mail_message *msg);
-void mapif_mail_getattach(int fd, int char_id, int mail_id);
-void mapif_parse_mail_getattach(int fd);
-void mapif_mail_delete(int fd, int char_id, int mail_id, bool failed);
-void mapif_parse_mail_delete(int fd);
-void mapif_mail_new(struct mail_message *msg);
-void mapif_mail_return(int fd, int char_id, int mail_id, int new_mail);
-void mapif_parse_mail_return(int fd);
-void mapif_mail_send(int fd, struct mail_message* msg);
-void mapif_parse_mail_send(int fd);
-bool mapif_mercenary_create(struct s_mercenary *merc);
-bool mapif_mercenary_save(const struct s_mercenary *merc);
-bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc);
-bool mapif_mercenary_delete(int merc_id);
-void mapif_mercenary_send(int fd, struct s_mercenary *merc, unsigned char flag);
-void mapif_parse_mercenary_create(int fd, const struct s_mercenary *merc);
-void mapif_parse_mercenary_load(int fd, int merc_id, int char_id);
-void mapif_mercenary_deleted(int fd, unsigned char flag);
-void mapif_parse_mercenary_delete(int fd, int merc_id);
-void mapif_mercenary_saved(int fd, unsigned char flag);
-void mapif_parse_mercenary_save(int fd, const struct s_mercenary *merc);
-int mapif_party_created(int fd, int account_id, int char_id, struct party *p);
-void mapif_party_noinfo(int fd, int party_id, int char_id);
-void mapif_party_info(int fd, struct party* p, int char_id);
-int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag);
-int mapif_party_optionchanged(int fd, struct party *p, int account_id, int flag);
-int mapif_party_withdraw(int party_id,int account_id, int char_id);
-int mapif_party_membermoved(struct party *p, int idx);
-int mapif_party_broken(int party_id, int flag);
-int mapif_party_message(int party_id, int account_id, const char *mes, int len, int sfd);
-int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const struct party_member *leader);
-void mapif_parse_PartyInfo(int fd, int party_id, int char_id);
-int mapif_parse_PartyAddMember(int fd, int party_id, const struct party_member *member);
-int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int item);
-int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id);
-int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv);
-int mapif_parse_BreakParty(int fd, int party_id);
-int mapif_parse_PartyMessage(int fd, int party_id, int account_id, const char *mes, int len);
-int mapif_parse_PartyLeaderChange(int fd, int party_id, int account_id, int char_id);
-int mapif_pet_created(int fd, int account_id, struct s_pet *p);
-int mapif_pet_info(int fd, int account_id, struct s_pet *p);
-int mapif_pet_noinfo(int fd, int account_id);
-int mapif_save_pet_ack(int fd, int account_id, int flag);
-int mapif_delete_pet_ack(int fd, int flag);
-int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short pet_lv, short pet_egg_id,
- short pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name);
-int mapif_load_pet(int fd, int account_id, int char_id, int pet_id);
-int mapif_save_pet(int fd, int account_id, const struct s_pet *data);
-int mapif_delete_pet(int fd, int pet_id);
-int mapif_parse_CreatePet(int fd);
-int mapif_parse_LoadPet(int fd);
-int mapif_parse_SavePet(int fd);
-int mapif_parse_DeletePet(int fd);
-struct quest *mapif_quests_fromsql(int char_id, int *count);
-bool mapif_quest_delete(int char_id, int quest_id);
-bool mapif_quest_add(int char_id, struct quest qd);
-bool mapif_quest_update(int char_id, struct quest qd);
-void mapif_quest_save_ack(int fd, int char_id, bool success);
-int mapif_parse_quest_save(int fd);
-void mapif_send_quests(int fd, int char_id, struct quest *tmp_questlog, int num_quests);
-int mapif_parse_quest_load(int fd);
-int mapif_load_guild_storage(int fd,int account_id,int guild_id, char flag);
-int mapif_save_guild_storage_ack(int fd, int account_id, int guild_id, int fail);
-int mapif_parse_LoadGuildStorage(int fd);
-int mapif_parse_SaveGuildStorage(int fd);
-int mapif_itembound_ack(int fd, int aid, int guild_id);
-int mapif_parse_ItemBoundRetrieve_sub(int fd);
-void mapif_parse_ItemBoundRetrieve(int fd);
-void mapif_parse_accinfo(int fd);
-void mapif_parse_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass,
- const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate, int group_id, int logincount, int state);
-int mapif_broadcast(const unsigned char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd);
-int mapif_wis_message(struct WisData *wd);
-void mapif_wis_response(int fd, const unsigned char *src, int flag);
-int mapif_wis_end(struct WisData *wd, int flag);
-int mapif_account_reg_reply(int fd,int account_id,int char_id, int type);
-int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason);
-int mapif_parse_broadcast(int fd);
-int mapif_parse_WisRequest(int fd);
-int mapif_parse_WisReply(int fd);
-int mapif_parse_WisToGM(int fd);
-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);
-
-struct mapif_interface mapif_s;
+static struct mapif_interface mapif_s;
struct mapif_interface *mapif;
-void mapif_defaults(void) {
+static void mapif_ban(int id, unsigned int flag, int status)
+{
+ // send to all map-servers to disconnect the player
+ unsigned char buf[11];
+ WBUFW(buf,0) = 0x2b14;
+ WBUFL(buf,2) = id;
+ WBUFB(buf,6) = flag; // 0: change of status, 1: ban
+ WBUFL(buf,7) = status; // status or final date of a banishment
+ mapif->sendall(buf, 11);
+}
+
+/// Initializes a server structure.
+static void mapif_server_init(int id)
+{
+ //memset(&chr->server[id], 0, sizeof(server[id]));
+ chr->server[id].fd = -1;
+}
+
+/// Destroys a server structure.
+static void mapif_server_destroy(int id)
+{
+ if (chr->server[id].fd == -1) {
+ sockt->close(chr->server[id].fd);
+ chr->server[id].fd = -1;
+ }
+}
+
+/// Resets all the data related to a server.
+static void mapif_server_reset(int id)
+{
+ int i, j;
+ unsigned char buf[16384];
+ int fd = chr->server[id].fd;
+ //Notify other map servers that this one is gone. [Skotlex]
+ WBUFW(buf, 0) = 0x2b20;
+ WBUFL(buf, 4) = htonl(chr->server[id].ip);
+ WBUFW(buf, 8) = htons(chr->server[id].port);
+ j = 0;
+ for (i = 0; i < VECTOR_LENGTH(chr->server[id].maps); i++) {
+ uint16 m = VECTOR_INDEX(chr->server[id].maps, i);
+ if (m != 0)
+ WBUFW(buf, 10 + (j++) * 4) = m;
+ }
+ if (j > 0) {
+ WBUFW(buf, 2) = j * 4 + 10;
+ mapif->sendallwos(fd, buf, WBUFW(buf, 2));
+ }
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", ragsrvinfo_db, chr->server[id].fd))
+ Sql_ShowDebug(inter->sql_handle);
+ chr->online_char_db->foreach(chr->online_char_db, chr->db_setoffline, id); //Tag relevant chars as 'in disconnected' server.
+ mapif->server_destroy(id);
+ mapif->server_init(id);
+}
+
+/// Called when the connection to a Map Server is disconnected.
+static void mapif_on_disconnect(int id)
+{
+ ShowStatus("Map-server #%d has disconnected.\n", id);
+ mapif->server_reset(id);
+}
+
+static void mapif_on_parse_accinfo(int account_id, int u_fd, int u_aid, int u_group, int map_fd)
+{
+ Assert_retv(chr->login_fd > 0);
+ WFIFOHEAD(chr->login_fd, 22);
+ WFIFOW(chr->login_fd, 0) = 0x2740;
+ WFIFOL(chr->login_fd, 2) = account_id;
+ WFIFOL(chr->login_fd, 6) = u_fd;
+ WFIFOL(chr->login_fd, 10) = u_aid;
+ WFIFOL(chr->login_fd, 14) = u_group;
+ WFIFOL(chr->login_fd, 18) = map_fd;
+ WFIFOSET(chr->login_fd, 22);
+}
+
+static void mapif_char_ban(int char_id, time_t timestamp)
+{
+ unsigned char buf[11];
+ WBUFW(buf, 0) = 0x2b14;
+ WBUFL(buf, 2) = char_id;
+ WBUFB(buf, 6) = 2;
+ WBUFL(buf, 7) = (unsigned int)timestamp;
+ mapif->sendall(buf, 11);
+}
+
+static int mapif_sendall(const unsigned char *buf, unsigned int len)
+{
+ int i, c;
+
+ nullpo_ret(buf);
+ c = 0;
+ for (i = 0; i < ARRAYLENGTH(chr->server); i++) {
+ int fd;
+ if ((fd = chr->server[i].fd) > 0) {
+ WFIFOHEAD(fd, len);
+ memcpy(WFIFOP(fd, 0), buf, len);
+ WFIFOSET(fd, len);
+ c++;
+ }
+ }
+
+ return c;
+}
+
+static int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
+{
+ int i, c;
+
+ nullpo_ret(buf);
+ c = 0;
+ for (i = 0; i < ARRAYLENGTH(chr->server); i++) {
+ int fd;
+ if ((fd = chr->server[i].fd) > 0 && fd != sfd) {
+ WFIFOHEAD(fd, len);
+ memcpy(WFIFOP(fd, 0), buf, len);
+ WFIFOSET(fd, len);
+ c++;
+ }
+ }
+
+ return c;
+}
+
+
+static int mapif_send(int fd, unsigned char *buf, unsigned int len)
+{
+ nullpo_ret(buf);
+ if (fd >= 0) {
+ int i;
+ ARR_FIND (0, ARRAYLENGTH(chr->server), i, fd == chr->server[i].fd);
+ if (i < ARRAYLENGTH(chr->server)) {
+ WFIFOHEAD(fd, len);
+ memcpy(WFIFOP(fd, 0), buf, len);
+ WFIFOSET(fd, len);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void mapif_send_users_count(int users)
+{
+ uint8 buf[6];
+ // send number of players to all map-servers
+ WBUFW(buf, 0) = 0x2b00;
+ WBUFL(buf, 2) = users;
+ mapif->sendall(buf, 6);
+}
+
+
+static void mapif_auction_message(int char_id, unsigned char result)
+{
+ unsigned char buf[74];
+
+ WBUFW(buf, 0) = 0x3854;
+ WBUFL(buf, 2) = char_id;
+ WBUFL(buf, 6) = result;
+ mapif->sendall(buf, 7);
+}
+
+static void mapif_auction_sendlist(int fd, int char_id, short count, short pages, unsigned char *buf)
+{
+ int len = (sizeof(struct auction_data) * count) + 12;
+
+ nullpo_retv(buf);
+
+ WFIFOHEAD(fd, len);
+ WFIFOW(fd, 0) = 0x3850;
+ WFIFOW(fd, 2) = len;
+ WFIFOL(fd, 4) = char_id;
+ WFIFOW(fd, 8) = count;
+ WFIFOW(fd, 10) = pages;
+ memcpy(WFIFOP(fd, 12), buf, len - 12);
+ WFIFOSET(fd, len);
+}
+
+static void mapif_parse_auction_requestlist(int fd)
+{
+ char searchtext[NAME_LENGTH];
+ int char_id = RFIFOL(fd, 4), len = sizeof(struct auction_data);
+ int price = RFIFOL(fd, 10);
+ short type = RFIFOW(fd, 8), page = max(1, RFIFOW(fd, 14));
+ unsigned char buf[5 * sizeof(struct auction_data)];
+ struct DBIterator *iter = db_iterator(inter_auction->db);
+ struct auction_data *auction;
+ short i = 0, j = 0, pages = 1;
+
+ memcpy(searchtext, RFIFOP(fd, 16), NAME_LENGTH);
+
+ for (auction = dbi_first(iter); dbi_exists(iter); auction = dbi_next(iter)) {
+ if ((type == 0 && auction->type != IT_ARMOR && auction->type != IT_PETARMOR)
+ || (type == 1 && auction->type != IT_WEAPON)
+ || (type == 2 && auction->type != IT_CARD)
+ || (type == 3 && auction->type != IT_ETC)
+ || (type == 4 && !strstr(auction->item_name, searchtext))
+ || (type == 5 && auction->price > price)
+ || (type == 6 && auction->seller_id != char_id)
+ || (type == 7 && auction->buyer_id != char_id))
+ continue;
+
+ i++;
+ if (i > 5) {
+ // Counting Pages of Total Results (5 Results per Page)
+ pages++;
+ i = 1; // First Result of This Page
+ }
+
+ if (page != pages)
+ continue; // This is not the requested Page
+
+ memcpy(WBUFP(buf, j * len), auction, len);
+ j++; // Found Results
+ }
+ dbi_destroy(iter);
+
+ mapif->auction_sendlist(fd, char_id, j, pages, buf);
+}
+
+static void mapif_auction_register(int fd, struct auction_data *auction)
+{
+ int len = sizeof(struct auction_data) + 4;
+
+ nullpo_retv(auction);
+
+ WFIFOHEAD(fd,len);
+ WFIFOW(fd, 0) = 0x3851;
+ WFIFOW(fd, 2) = len;
+ memcpy(WFIFOP(fd, 4), auction, sizeof(struct auction_data));
+ WFIFOSET(fd, len);
+}
+
+static void mapif_parse_auction_register(int fd)
+{
+ struct auction_data auction;
+ if( RFIFOW(fd, 2) != sizeof(struct auction_data) + 4 )
+ return;
+
+ memcpy(&auction, RFIFOP(fd, 4), sizeof(struct auction_data));
+ if( inter_auction->count(auction.seller_id, false) < 5 )
+ auction.auction_id = inter_auction->create(&auction);
+
+ mapif->auction_register(fd, &auction);
+}
+
+static void mapif_auction_cancel(int fd, int char_id, unsigned char result)
+{
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3852;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOB(fd, 6) = result;
+ WFIFOSET(fd, 7);
+}
+
+static void mapif_parse_auction_cancel(int fd)
+{
+ int char_id = RFIFOL(fd, 2), auction_id = RFIFOL(fd, 6);
+ struct auction_data *auction;
+
+ if ((auction = (struct auction_data *)idb_get(inter_auction->db, auction_id)) == NULL) {
+ mapif->auction_cancel(fd, char_id, 1); // Bid Number is Incorrect
+ return;
+ }
+
+ if (auction->seller_id != char_id) {
+ mapif->auction_cancel(fd, char_id, 2); // You cannot end the auction
+ return;
+ }
+
+ if (auction->buyer_id > 0) {
+ mapif->auction_cancel(fd, char_id, 3); // An auction with at least one bidder cannot be canceled
+ return;
+ }
+
+ inter_mail->sendmail(0, "Auction Manager", auction->seller_id, auction->seller_name, "Auction", "Auction canceled.", 0, &auction->item);
+ inter_auction->delete_(auction);
+
+ mapif->auction_cancel(fd, char_id, 0); // The auction has been canceled
+}
+
+
+static void mapif_auction_close(int fd, int char_id, unsigned char result)
+{
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3853;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOB(fd, 6) = result;
+ WFIFOSET(fd, 7);
+}
+
+static void mapif_parse_auction_close(int fd)
+{
+ int char_id = RFIFOL(fd, 2), auction_id = RFIFOL(fd, 6);
+ struct auction_data *auction;
+
+ if ((auction = (struct auction_data *)idb_get(inter_auction->db, auction_id)) == NULL) {
+ mapif->auction_close(fd, char_id, 2); // Bid Number is Incorrect
+ return;
+ }
+
+ if (auction->seller_id != char_id) {
+ mapif->auction_close(fd, char_id, 1); // You cannot end the auction
+ return;
+ }
+
+ if (auction->buyer_id == 0) {
+ mapif->auction_close(fd, char_id, 1); // You cannot end the auction
+ return;
+ }
+
+ // Send Money to Seller
+ inter_mail->sendmail(0, "Auction Manager", auction->seller_id, auction->seller_name, "Auction", "Auction closed.", auction->price, NULL);
+ // Send Item to Buyer
+ inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "Auction winner.", 0, &auction->item);
+ mapif->auction_message(auction->buyer_id, 6); // You have won the auction
+ inter_auction->delete_(auction);
+
+ mapif->auction_close(fd, char_id, 0); // You have ended the auction
+}
+
+static void mapif_auction_bid(int fd, int char_id, int bid, unsigned char result)
+{
+ WFIFOHEAD(fd, 11);
+ WFIFOW(fd, 0) = 0x3855;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOL(fd, 6) = bid; // To Return Zeny
+ WFIFOB(fd, 10) = result;
+ WFIFOSET(fd, 11);
+}
+
+static void mapif_parse_auction_bid(int fd)
+{
+ int char_id = RFIFOL(fd, 4), bid = RFIFOL(fd, 12);
+ unsigned int auction_id = RFIFOL(fd, 8);
+ struct auction_data *auction;
+
+ if ((auction = (struct auction_data *)idb_get(inter_auction->db, auction_id)) == NULL || auction->price >= bid || auction->seller_id == char_id) {
+ mapif->auction_bid(fd, char_id, bid, 0); // You have failed to bid in the auction
+ return;
+ }
+
+ if (inter_auction->count(char_id, true) > 4 && bid < auction->buynow && auction->buyer_id != char_id) {
+ mapif->auction_bid(fd, char_id, bid, 9); // You cannot place more than 5 bids at a time
+ return;
+ }
+
+ if (auction->buyer_id > 0) {
+ // Send Money back to the previous Buyer
+ if (auction->buyer_id != char_id) {
+ inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "Someone has placed a higher bid.", auction->price, NULL);
+ mapif->auction_message(auction->buyer_id, 7); // You have failed to win the auction
+ } else {
+ inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "You have placed a higher bid.", auction->price, NULL);
+ }
+ }
+
+ auction->buyer_id = char_id;
+ safestrncpy(auction->buyer_name, RFIFOP(fd, 16), NAME_LENGTH);
+ auction->price = bid;
+
+ if (bid >= auction->buynow) {
+ // Automatic won the auction
+ mapif->auction_bid(fd, char_id, bid - auction->buynow, 1); // You have successfully bid in the auction
+
+ inter_mail->sendmail(0, "Auction Manager", auction->buyer_id, auction->buyer_name, "Auction", "You have won the auction.", 0, &auction->item);
+ mapif->auction_message(char_id, 6); // You have won the auction
+ inter_mail->sendmail(0, "Auction Manager", auction->seller_id, auction->seller_name, "Auction", "Payment for your auction!.", auction->buynow, NULL);
+
+ inter_auction->delete_(auction);
+ return;
+ }
+
+ inter_auction->save(auction);
+
+ mapif->auction_bid(fd, char_id, 0, 1); // You have successfully bid in the auction
+}
+
+static void mapif_elemental_send(int fd, struct s_elemental *ele, unsigned char flag)
+{
+ int size = sizeof(struct s_elemental) + 5;
+
+ nullpo_retv(ele);
+ WFIFOHEAD(fd, size);
+ WFIFOW(fd, 0) = 0x387c;
+ WFIFOW(fd, 2) = size;
+ WFIFOB(fd, 4) = flag;
+ memcpy(WFIFOP(fd, 5), ele, sizeof(struct s_elemental));
+ WFIFOSET(fd, size);
+}
+
+static void mapif_parse_elemental_create(int fd, const struct s_elemental *ele)
+{
+ struct s_elemental ele_;
+ bool result;
+
+ memcpy(&ele_, ele, sizeof(ele_));
+
+ result = inter_elemental->create(&ele_);
+ mapif->elemental_send(fd, &ele_, result);
+}
+
+static void mapif_parse_elemental_load(int fd, int ele_id, int char_id)
+{
+ struct s_elemental ele;
+ bool result = inter_elemental->load(ele_id, char_id, &ele);
+ mapif->elemental_send(fd, &ele, result);
+}
+
+static void mapif_elemental_deleted(int fd, unsigned char flag)
+{
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x387d;
+ WFIFOB(fd, 2) = flag;
+ WFIFOSET(fd, 3);
+}
+
+static void mapif_parse_elemental_delete(int fd, int ele_id)
+{
+ bool result = inter_elemental->delete(ele_id);
+ mapif->elemental_deleted(fd, result);
+}
+
+static void mapif_elemental_saved(int fd, unsigned char flag)
+{
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x387e;
+ WFIFOB(fd, 2) = flag;
+ WFIFOSET(fd, 3);
+}
+
+static void mapif_parse_elemental_save(int fd, const struct s_elemental *ele)
+{
+ bool result = inter_elemental->save(ele);
+ mapif->elemental_saved(fd, result);
+}
+
+static int mapif_guild_created(int fd, int account_id, struct guild *g)
+{
+ WFIFOHEAD(fd, 10);
+ WFIFOW(fd, 0) = 0x3830;
+ WFIFOL(fd, 2) = account_id;
+ if (g != NULL) {
+ WFIFOL(fd, 6) = g->guild_id;
+ ShowInfo("int_guild: Guild created (%d - %s)\n", g->guild_id, g->name);
+ } else {
+ WFIFOL(fd, 6) = 0;
+ }
+
+ WFIFOSET(fd, 10);
+ return 0;
+}
+
+// Guild not found
+static int mapif_guild_noinfo(int fd, int guild_id)
+{
+ unsigned char buf[12];
+ WBUFW(buf, 0) = 0x3831;
+ WBUFW(buf, 2) = 8;
+ WBUFL(buf, 4) = guild_id;
+ ShowWarning("int_guild: info not found %d\n", guild_id);
+ if (fd < 0)
+ mapif->sendall(buf, 8);
+ else
+ mapif->send(fd,buf, 8);
+ return 0;
+}
+
+// Send guild info
+static int mapif_guild_info(int fd, struct guild *g)
+{
+ unsigned char buf[8 + sizeof(struct guild)];
+ nullpo_ret(g);
+ WBUFW(buf, 0) = 0x3831;
+ WBUFW(buf, 2) = 4 + sizeof(struct guild);
+ memcpy(buf + 4, g, sizeof(struct guild));
+ if (fd < 0)
+ mapif->sendall(buf, WBUFW(buf, 2));
+ else
+ mapif->send(fd, buf, WBUFW(buf, 2));
+ return 0;
+}
+
+// ACK member add
+static int mapif_guild_memberadded(int fd, int guild_id, int account_id, int char_id, int flag)
+{
+ WFIFOHEAD(fd, 15);
+ WFIFOW(fd, 0) = 0x3832;
+ WFIFOL(fd, 2) = guild_id;
+ WFIFOL(fd, 6) = account_id;
+ WFIFOL(fd, 10) = char_id;
+ WFIFOB(fd, 14) = flag;
+ WFIFOSET(fd, 15);
+ return 0;
+}
+
+// ACK member leave
+static int mapif_guild_withdraw(int guild_id, int account_id, int char_id, int flag, const char *name, const char *mes)
+{
+ unsigned char buf[55 + NAME_LENGTH];
+
+ nullpo_ret(name);
+ nullpo_ret(mes);
+
+ WBUFW(buf, 0) = 0x3834;
+ WBUFL(buf, 2) = guild_id;
+ WBUFL(buf, 6) = account_id;
+ WBUFL(buf, 10) = char_id;
+ WBUFB(buf, 14) = flag;
+ memcpy(WBUFP(buf, 15), mes, 40);
+ memcpy(WBUFP(buf, 55), name, NAME_LENGTH);
+ mapif->sendall(buf, 55 + NAME_LENGTH);
+ ShowInfo("int_guild: guild withdraw (%d - %d: %s - %s)\n", guild_id, account_id, name, mes);
+ return 0;
+}
+
+// Send short member's info
+static int mapif_guild_memberinfoshort(struct guild *g, int idx)
+{
+ unsigned char buf[23];
+ nullpo_ret(g);
+ Assert_ret(idx >= 0 && idx < MAX_GUILD);
+ WBUFW(buf, 0) = 0x3835;
+ WBUFL(buf, 2) = g->guild_id;
+ WBUFL(buf, 6) = g->member[idx].account_id;
+ WBUFL(buf, 10) = g->member[idx].char_id;
+ WBUFB(buf, 14) = (unsigned char)g->member[idx].online;
+ WBUFW(buf, 15) = g->member[idx].lv;
+ WBUFW(buf, 17) = g->member[idx].class;
+ WBUFL(buf, 19) = g->member[idx].last_login;
+ mapif->sendall(buf, 23);
+ return 0;
+}
+
+// Send guild broken
+static int mapif_guild_broken(int guild_id, int flag)
+{
+ unsigned char buf[7];
+ WBUFW(buf, 0) = 0x3836;
+ WBUFL(buf, 2) = guild_id;
+ WBUFB(buf, 6) = flag;
+ mapif->sendall(buf, 7);
+ ShowInfo("int_guild: Guild broken (%d)\n", guild_id);
+ return 0;
+}
+
+// Send guild message
+static int mapif_guild_message(int guild_id, int account_id, const char *mes, int len, int sfd)
+{
+ unsigned char buf[512];
+ nullpo_ret(mes);
+ if (len > 500)
+ len = 500;
+ WBUFW(buf, 0) = 0x3837;
+ WBUFW(buf, 2) = len + 12;
+ WBUFL(buf, 4) = guild_id;
+ WBUFL(buf, 8) = account_id;
+ memcpy(WBUFP(buf, 12), mes, len);
+ mapif->sendallwos(sfd, buf, len + 12);
+ return 0;
+}
+
+// Send basic info
+static int mapif_guild_basicinfochanged(int guild_id, int type, const void *data, int len)
+{
+ unsigned char buf[2048];
+ nullpo_ret(data);
+ if (len > 2038)
+ len = 2038;
+ WBUFW(buf, 0) = 0x3839;
+ WBUFW(buf, 2) = len + 10;
+ WBUFL(buf, 4) = guild_id;
+ WBUFW(buf, 8) = type;
+ memcpy(WBUFP(buf, 10), data, len);
+ mapif->sendall(buf, len + 10);
+ return 0;
+}
+
+// Send member info
+static int mapif_guild_memberinfochanged(int guild_id, int account_id, int char_id, int type, const void *data, int len)
+{
+ unsigned char buf[2048];
+ nullpo_ret(data);
+ if (len > 2030)
+ len = 2030;
+ WBUFW(buf, 0) = 0x383a;
+ WBUFW(buf, 2) = len + 18;
+ WBUFL(buf, 4) = guild_id;
+ WBUFL(buf, 8) = account_id;
+ WBUFL(buf, 12) = char_id;
+ WBUFW(buf, 16) = type;
+ memcpy(WBUFP(buf, 18), data, len);
+ mapif->sendall(buf, len + 18);
+ return 0;
+}
+
+// ACK guild skill up
+static int mapif_guild_skillupack(int guild_id, uint16 skill_id, int account_id)
+{
+ unsigned char buf[14];
+ WBUFW(buf, 0) = 0x383c;
+ WBUFL(buf, 2) = guild_id;
+ WBUFL(buf, 6) = skill_id;
+ WBUFL(buf,10) = account_id;
+ mapif->sendall(buf, 14);
+ return 0;
+}
+
+// ACK guild alliance
+static int mapif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag, const char *name1, const char *name2)
+{
+ unsigned char buf[19 + 2 * NAME_LENGTH];
+ nullpo_ret(name1);
+ nullpo_ret(name2);
+ WBUFW(buf, 0) = 0x383d;
+ WBUFL(buf, 2) = guild_id1;
+ WBUFL(buf, 6) = guild_id2;
+ WBUFL(buf, 10) = account_id1;
+ WBUFL(buf, 14) = account_id2;
+ WBUFB(buf, 18) = flag;
+ memcpy(WBUFP(buf, 19), name1, NAME_LENGTH);
+ memcpy(WBUFP(buf, 19 + NAME_LENGTH), name2, NAME_LENGTH);
+ mapif->sendall(buf,19 + 2 * NAME_LENGTH);
+ return 0;
+}
+
+// Send a guild position desc
+static int mapif_guild_position(struct guild *g, int idx)
+{
+ unsigned char buf[12 + sizeof(struct guild_position)];
+ nullpo_ret(g);
+ Assert_ret(idx >= 0 && idx < MAX_GUILDPOSITION);
+ WBUFW(buf, 0) = 0x383b;
+ WBUFW(buf, 2) = sizeof(struct guild_position)+12;
+ WBUFL(buf, 4) = g->guild_id;
+ WBUFL(buf, 8) = idx;
+ memcpy(WBUFP(buf, 12), &g->position[idx], sizeof(struct guild_position));
+ mapif->sendall(buf, WBUFW(buf, 2));
+ return 0;
+}
+
+// Send the guild notice
+static int mapif_guild_notice(struct guild *g)
+{
+ unsigned char buf[256];
+ nullpo_ret(g);
+ WBUFW(buf, 0) = 0x383e;
+ WBUFL(buf, 2) = g->guild_id;
+ memcpy(WBUFP(buf, 6), g->mes1, MAX_GUILDMES1);
+ memcpy(WBUFP(buf, 66), g->mes2, MAX_GUILDMES2);
+ mapif->sendall(buf, 186);
+ return 0;
+}
+
+// Send emblem data
+static int mapif_guild_emblem(struct guild *g)
+{
+ unsigned char buf[12 + sizeof(g->emblem_data)];
+ nullpo_ret(g);
+ WBUFW(buf, 0) = 0x383f;
+ WBUFW(buf, 2) = g->emblem_len+12;
+ WBUFL(buf, 4) = g->guild_id;
+ WBUFL(buf, 8) = g->emblem_id;
+ memcpy(WBUFP(buf, 12), g->emblem_data, g->emblem_len);
+ mapif->sendall(buf, WBUFW(buf, 2));
+ return 0;
+}
+
+static int mapif_guild_master_changed(struct guild *g, int aid, int cid)
+{
+ unsigned char buf[14];
+ nullpo_ret(g);
+ WBUFW(buf, 0) = 0x3843;
+ WBUFL(buf, 2) = g->guild_id;
+ WBUFL(buf, 6) = aid;
+ WBUFL(buf, 10) = cid;
+ mapif->sendall(buf, 14);
+ return 0;
+}
+
+static int mapif_guild_castle_dataload(int fd, int sz, const int *castle_ids)
+{
+ struct guild_castle *gc = NULL;
+ int num = (sz - 4) / sizeof(int);
+ int len = 4 + num * sizeof(*gc);
+ int i;
+
+ nullpo_ret(castle_ids);
+ WFIFOHEAD(fd, len);
+ WFIFOW(fd, 0) = 0x3840;
+ WFIFOW(fd, 2) = len;
+ for (i = 0; i < num; i++) {
+ gc = inter_guild->castle_fromsql(*(castle_ids++));
+ memcpy(WFIFOP(fd, 4 + i * sizeof(*gc)), gc, sizeof(*gc));
+ }
+ WFIFOSET(fd, len);
+ return 0;
+}
+
+// Guild creation request
+static int mapif_parse_CreateGuild(int fd, int account_id, const char *name, const struct guild_member *master)
+{
+ struct guild *g;
+ nullpo_ret(name);
+ nullpo_ret(master);
+
+ g = inter_guild->create(name, master);
+
+ // Report to client
+ mapif->guild_created(fd,account_id,g);
+ if (g != NULL) {
+ mapif->guild_info(fd,g);
+ }
+
+ return 0;
+}
+
+// Return guild info to client
+static int mapif_parse_GuildInfo(int fd, int guild_id)
+{
+ struct guild * g = inter_guild->fromsql(guild_id); //We use this because on start-up the info of castle-owned guilds is required. [Skotlex]
+ if (g != NULL) {
+ if (!inter_guild->calcinfo(g))
+ mapif->guild_info(fd, g);
+ } else {
+ mapif->guild_noinfo(fd, guild_id); // Failed to load info
+ }
+ return 0;
+}
+
+// Add member to guild
+static int mapif_parse_GuildAddMember(int fd, int guild_id, const struct guild_member *m)
+{
+ nullpo_ret(m);
+
+ inter_guild->add_member(guild_id, m, fd);
+ return 0;
+}
+
+// Delete member from guild
+static int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes)
+{
+ inter_guild->leave(guild_id, account_id, char_id, flag, mes, fd);
+ return 0;
+}
+
+// Change member info
+static int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id, int char_id, int online, int lv, int16 class)
+{
+ inter_guild->update_member_info_short(guild_id, account_id, char_id, online, lv, class);
+ return 0;
+}
+
+// BreakGuild
+static int mapif_parse_BreakGuild(int fd, int guild_id)
+{
+ inter_guild->disband(guild_id);
+ return 0;
+}
+
+// Forward Guild message to others map servers
+static int mapif_parse_GuildMessage(int fd, int guild_id, int account_id, const char *mes, int len)
+{
+ return mapif->guild_message(guild_id,account_id,mes,len, fd);
+}
+
+/**
+ * Changes basic guild information
+ * The types are available in mmo.h::guild_basic_info
+ **/
+static int mapif_parse_GuildBasicInfoChange(int fd, int guild_id, int type, const void *data, int len)
+{
+ inter_guild->update_basic_info(guild_id, type, data, len);
+ // Information is already sent in mapif->guild_info
+ //mapif->guild_basicinfochanged(guild_id,type,data,len);
+ return 0;
+}
+
+// Modification of the guild
+static int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int char_id, int type, const char *data, int len)
+{
+ inter_guild->update_member_info(guild_id, account_id, char_id, type, data, len);
+ return 0;
+}
+
+// Change a position desc
+static int mapif_parse_GuildPosition(int fd, int guild_id, int idx, const struct guild_position *p)
+{
+ nullpo_ret(p);
+ inter_guild->update_position(guild_id, idx, p);
+ return 0;
+}
+
+// Guild Skill UP
+static int mapif_parse_GuildSkillUp(int fd, int guild_id, uint16 skill_id, int account_id, int max)
+{
+ inter_guild->use_skill_point(guild_id, skill_id, account_id, max);
+ return 0;
+}
+
+// Alliance modification
+static int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_id1, int account_id2, int flag)
+{
+ inter_guild->change_alliance(guild_id1, guild_id2, account_id1, account_id2, flag);
+ return 0;
+}
+
+// Change guild message
+static int mapif_parse_GuildNotice(int fd, int guild_id, const char *mes1, const char *mes2)
+{
+ inter_guild->update_notice(guild_id, mes1, mes2);
+ return 0;
+}
+
+static int mapif_parse_GuildEmblem(int fd, int len, int guild_id, int dummy, const char *data)
+{
+ inter_guild->update_emblem(len, guild_id, data);
+ return 0;
+}
+
+static int mapif_parse_GuildCastleDataLoad(int fd, int len, const int *castle_ids)
+{
+ return mapif->guild_castle_dataload(fd, len, castle_ids);
+}
+
+static int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
+{
+ inter_guild->update_castle_data(castle_id, index, value);
+ return 0;
+}
+
+static int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int len)
+{
+ inter_guild->change_leader(guild_id, name, len);
+ return 0;
+}
+
+static void mapif_homunculus_created(int fd, int account_id, const struct s_homunculus *sh, unsigned char flag)
+{
+ nullpo_retv(sh);
+ WFIFOHEAD(fd, sizeof(struct s_homunculus) + 9);
+ WFIFOW(fd, 0) = 0x3890;
+ WFIFOW(fd, 2) = sizeof(struct s_homunculus) + 9;
+ WFIFOL(fd, 4) = account_id;
+ WFIFOB(fd, 8) = flag;
+ memcpy(WFIFOP(fd, 9), sh, sizeof(struct s_homunculus));
+ WFIFOSET(fd, WFIFOW(fd, 2));
+}
+
+static void mapif_homunculus_deleted(int fd, int flag)
+{
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x3893;
+ WFIFOB(fd,2) = flag; //Flag 1 = success
+ WFIFOSET(fd, 3);
+}
+
+static void mapif_homunculus_loaded(int fd, int account_id, struct s_homunculus *hd)
+{
+ WFIFOHEAD(fd, sizeof(struct s_homunculus) + 9);
+ WFIFOW(fd, 0) = 0x3891;
+ WFIFOW(fd, 2) = sizeof(struct s_homunculus) + 9;
+ WFIFOL(fd, 4) = account_id;
+ if (hd != NULL) {
+ WFIFOB(fd, 8) = 1; // success
+ memcpy(WFIFOP(fd, 9), hd, sizeof(struct s_homunculus));
+ } else {
+ WFIFOB(fd, 8) = 0; // not found.
+ memset(WFIFOP(fd, 9), 0, sizeof(struct s_homunculus));
+ }
+ WFIFOSET(fd, sizeof(struct s_homunculus) + 9);
+}
+
+static void mapif_homunculus_saved(int fd, int account_id, bool flag)
+{
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3892;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOB(fd, 6) = flag; // 1:success, 0:failure
+ WFIFOSET(fd, 7);
+}
+
+static void mapif_homunculus_renamed(int fd, int account_id, int char_id, unsigned char flag, const char *name)
+{
+ nullpo_retv(name);
+ WFIFOHEAD(fd, NAME_LENGTH + 12);
+ WFIFOW(fd, 0) = 0x3894;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOL(fd, 6) = char_id;
+ WFIFOB(fd, 10) = flag;
+ safestrncpy(WFIFOP(fd, 11), name, NAME_LENGTH);
+ WFIFOSET(fd, NAME_LENGTH + 12);
+}
+
+static void mapif_parse_homunculus_create(int fd, int len, int account_id, const struct s_homunculus *phd)
+{
+ struct s_homunculus shd;
+ bool result;
+
+ memcpy(&shd, phd, sizeof(shd));
+
+ result = inter_homunculus->create(&shd);
+ mapif->homunculus_created(fd, account_id, &shd, result);
+}
+
+static void mapif_parse_homunculus_delete(int fd, int homun_id)
+{
+ bool result = inter_homunculus->delete(homun_id);
+ mapif->homunculus_deleted(fd, result);
+}
+
+static void mapif_parse_homunculus_load(int fd, int account_id, int homun_id)
+{
+ struct s_homunculus hd;
+ bool result = inter_homunculus->load(homun_id, &hd);
+ mapif->homunculus_loaded(fd, account_id, (result ? &hd : NULL));
+}
+
+static void mapif_parse_homunculus_save(int fd, int len, int account_id, const struct s_homunculus *phd)
+{
+ bool result = inter_homunculus->save(phd);
+ mapif->homunculus_saved(fd, account_id, result);
+}
+
+static void mapif_parse_homunculus_rename(int fd, int account_id, int char_id, const char *name)
+{
+ bool result = inter_homunculus->rename(name);
+ mapif->homunculus_renamed(fd, account_id, char_id, result, name);
+}
+
+static void mapif_mail_sendinbox(int fd, int char_id, unsigned char flag, struct mail_data *md)
+{
+ nullpo_retv(md);
+ //FIXME: dumping the whole structure like this is unsafe [ultramage]
+ WFIFOHEAD(fd, sizeof(struct mail_data) + 9);
+ 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),md,sizeof(struct mail_data));
+ WFIFOSET(fd,WFIFOW(fd, 2));
+}
+
+/*==========================================
+ * Client Inbox Request
+ *------------------------------------------*/
+static void mapif_parse_mail_requestinbox(int fd)
+{
+ int char_id = RFIFOL(fd, 2);
+ unsigned char flag = RFIFOB(fd, 6);
+ struct mail_data md;
+ memset(&md, 0, sizeof(md));
+ inter_mail->fromsql(char_id, &md);
+ mapif->mail_sendinbox(fd, char_id, flag, &md);
+}
+
+/*==========================================
+ * Mark mail as 'Read'
+ *------------------------------------------*/
+static void mapif_parse_mail_read(int fd)
+{
+ int mail_id = RFIFOL(fd, 2);
+ inter_mail->mark_read(mail_id);
+}
+
+static void mapif_mail_sendattach(int fd, int char_id, struct mail_message *msg)
+{
+ nullpo_retv(msg);
+ 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) = (msg->zeny > 0) ? msg->zeny : 0;
+ memcpy(WFIFOP(fd, 12), &msg->item, sizeof(struct item));
+ WFIFOSET(fd,WFIFOW(fd, 2));
+}
+
+static void mapif_parse_mail_getattach(int fd)
+{
+ struct mail_message msg = { 0 };
+ int char_id = RFIFOL(fd, 2);
+ int mail_id = RFIFOL(fd, 6);
+
+ if (!inter_mail->get_attachment(char_id, mail_id, &msg))
+ return;
+
+ mapif->mail_sendattach(fd, char_id, &msg);
+}
+
+/*==========================================
+ * Delete Mail
+ *------------------------------------------*/
+static void mapif_mail_delete(int fd, int char_id, int mail_id, bool failed)
+{
+ WFIFOHEAD(fd, 11);
+ WFIFOW(fd, 0) = 0x384b;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOL(fd, 6) = mail_id;
+ WFIFOB(fd, 10) = failed;
+ WFIFOSET(fd, 11);
+}
+
+static void mapif_parse_mail_delete(int fd)
+{
+ int char_id = RFIFOL(fd, 2);
+ int mail_id = RFIFOL(fd, 6);
+ bool failed = !inter_mail->delete(char_id, mail_id);
+ mapif->mail_delete(fd, char_id, mail_id, failed);
+}
+
+/*==========================================
+ * Report New Mail to Map Server
+ *------------------------------------------*/
+static void mapif_mail_new(struct mail_message *msg)
+{
+ unsigned char buf[74];
+
+ if (msg == NULL || msg->id == 0)
+ return;
+
+ WBUFW(buf, 0) = 0x3849;
+ WBUFL(buf, 2) = msg->dest_id;
+ WBUFL(buf, 6) = msg->id;
+ memcpy(WBUFP(buf, 10), msg->send_name, NAME_LENGTH);
+ memcpy(WBUFP(buf, 34), msg->title, MAIL_TITLE_LENGTH);
+ mapif->sendall(buf, 74);
+}
+
+/*==========================================
+ * Return Mail
+ *------------------------------------------*/
+static void mapif_mail_return(int fd, int char_id, int mail_id, int new_mail)
+{
+ WFIFOHEAD(fd, 11);
+ WFIFOW(fd, 0) = 0x384c;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOL(fd, 6) = mail_id;
+ WFIFOB(fd, 10) = (new_mail == 0);
+ WFIFOSET(fd, 11);
+}
+
+static void mapif_parse_mail_return(int fd)
+{
+ int char_id = RFIFOL(fd, 2);
+ int mail_id = RFIFOL(fd, 6);
+ int new_mail = 0;
+
+ if (!inter_mail->return_message(char_id, mail_id, &new_mail))
+ return;
+
+ mapif->mail_return(fd, char_id, mail_id, new_mail);
+}
+
+/*==========================================
+ * Send Mail
+ *------------------------------------------*/
+static void mapif_mail_send(int fd, struct mail_message* msg)
+{
+ int len = sizeof(struct mail_message) + 4;
+
+ nullpo_retv(msg);
+ WFIFOHEAD(fd, len);
+ WFIFOW(fd, 0) = 0x384d;
+ WFIFOW(fd, 2) = len;
+ memcpy(WFIFOP(fd, 4), msg, sizeof(struct mail_message));
+ WFIFOSET(fd,len);
+}
+
+static void mapif_parse_mail_send(int fd)
+{
+ struct mail_message msg;
+ int account_id = 0;
+
+ if (RFIFOW(fd, 2) != 8 + sizeof(struct mail_message))
+ return;
+
+ account_id = RFIFOL(fd, 4);
+ memcpy(&msg, RFIFOP(fd, 8), sizeof(struct mail_message));
+
+ inter_mail->send(account_id, &msg);
+
+ mapif->mail_send(fd, &msg); // notify sender
+ mapif->mail_new(&msg); // notify recipient
+}
+
+static void mapif_mercenary_send(int fd, struct s_mercenary *merc, unsigned char flag)
+{
+ int size = sizeof(struct s_mercenary) + 5;
+
+ nullpo_retv(merc);
+ WFIFOHEAD(fd, size);
+ WFIFOW(fd, 0) = 0x3870;
+ WFIFOW(fd, 2) = size;
+ WFIFOB(fd, 4) = flag;
+ memcpy(WFIFOP(fd, 5), merc, sizeof(struct s_mercenary));
+ WFIFOSET(fd,size);
+}
+
+static void mapif_parse_mercenary_create(int fd, const struct s_mercenary *merc)
+{
+ struct s_mercenary merc_;
+ bool result;
+
+ memcpy(&merc_, merc, sizeof(merc_));
+
+ result = inter_mercenary->create(&merc_);
+ mapif->mercenary_send(fd, &merc_, result);
+}
+
+static void mapif_parse_mercenary_load(int fd, int merc_id, int char_id)
+{
+ struct s_mercenary merc;
+ bool result = inter_mercenary->load(merc_id, char_id, &merc);
+ mapif->mercenary_send(fd, &merc, result);
+}
+
+static void mapif_mercenary_deleted(int fd, unsigned char flag)
+{
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x3871;
+ WFIFOB(fd, 2) = flag;
+ WFIFOSET(fd, 3);
+}
+
+static void mapif_parse_mercenary_delete(int fd, int merc_id)
+{
+ bool result = inter_mercenary->delete(merc_id);
+ mapif->mercenary_deleted(fd, result);
+}
+
+static void mapif_mercenary_saved(int fd, unsigned char flag)
+{
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x3872;
+ WFIFOB(fd, 2) = flag;
+ WFIFOSET(fd, 3);
+}
+
+static void mapif_parse_mercenary_save(int fd, const struct s_mercenary *merc)
+{
+ bool result = inter_mercenary->save(merc);
+ mapif->mercenary_saved(fd, result);
+}
+
+// Create a party whether or not
+static int mapif_party_created(int fd, int account_id, int char_id, struct party *p)
+{
+ WFIFOHEAD(fd, 39);
+ WFIFOW(fd, 0) = 0x3820;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOL(fd, 6) = char_id;
+ if (p != NULL) {
+ WFIFOB(fd, 10) = 0;
+ WFIFOL(fd, 11) = p->party_id;
+ memcpy(WFIFOP(fd, 15), p->name, NAME_LENGTH);
+ ShowInfo("int_party: Party created (%d - %s)\n", p->party_id, p->name);
+ } else {
+ WFIFOB(fd, 10) = 1;
+ WFIFOL(fd, 11) = 0;
+ memset(WFIFOP(fd, 15), 0, NAME_LENGTH);
+ }
+ WFIFOSET(fd, 39);
+
+ return 0;
+}
+
+//Party information not found
+static void mapif_party_noinfo(int fd, int party_id, int char_id)
+{
+ WFIFOHEAD(fd, 12);
+ WFIFOW(fd, 0) = 0x3821;
+ WFIFOW(fd, 2) = 12;
+ WFIFOL(fd, 4) = char_id;
+ WFIFOL(fd, 8) = party_id;
+ WFIFOSET(fd, 12);
+ ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id);
+}
+
+//Digest party information
+static void mapif_party_info(int fd, struct party* p, int char_id)
+{
+ unsigned char buf[8 + sizeof(struct party)];
+ nullpo_retv(p);
+ WBUFW(buf, 0) = 0x3821;
+ WBUFW(buf, 2) = 8 + sizeof(struct party);
+ WBUFL(buf, 4) = char_id;
+ memcpy(WBUFP(buf, 8), p, sizeof(struct party));
+
+ if (fd < 0)
+ mapif->sendall(buf, WBUFW(buf, 2));
+ else
+ mapif->send(fd, buf, WBUFW(buf, 2));
+}
+
+//Whether or not additional party members
+static int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag)
+{
+ WFIFOHEAD(fd, 15);
+ WFIFOW(fd, 0) = 0x3822;
+ WFIFOL(fd, 2) = party_id;
+ WFIFOL(fd, 6) = account_id;
+ WFIFOL(fd, 10) = char_id;
+ WFIFOB(fd, 14) = flag;
+ WFIFOSET(fd, 15);
+
+ return 0;
+}
+
+// Party setting change notification
+static int mapif_party_optionchanged(int fd, struct party *p, int account_id, int flag)
+{
+ unsigned char buf[16];
+ nullpo_ret(p);
+ WBUFW(buf, 0) = 0x3823;
+ WBUFL(buf, 2) = p->party_id;
+ WBUFL(buf, 6) = account_id;
+ WBUFW(buf, 10) = p->exp;
+ WBUFW(buf, 12) = p->item;
+ WBUFB(buf, 14) = flag;
+ if (flag == 0)
+ mapif->sendall(buf, 15);
+ else
+ mapif->send(fd, buf, 15);
+ return 0;
+}
+
+//Withdrawal notification party
+static int mapif_party_withdraw(int party_id, int account_id, int char_id)
+{
+ unsigned char buf[16];
+
+ WBUFW(buf, 0) = 0x3824;
+ WBUFL(buf, 2) = party_id;
+ WBUFL(buf, 6) = account_id;
+ WBUFL(buf, 10) = char_id;
+ mapif->sendall(buf, 14);
+ return 0;
+}
+
+//Party map update notification
+static int mapif_party_membermoved(struct party *p, int idx)
+{
+ unsigned char buf[20];
+
+ nullpo_ret(p);
+ Assert_ret(idx >= 0 && idx < MAX_PARTY);
+ WBUFW(buf, 0) = 0x3825;
+ WBUFL(buf, 2) = p->party_id;
+ WBUFL(buf, 6) = p->member[idx].account_id;
+ WBUFL(buf, 10) = p->member[idx].char_id;
+ WBUFW(buf, 14) = p->member[idx].map;
+ WBUFB(buf, 16) = p->member[idx].online;
+ WBUFW(buf, 17) = p->member[idx].lv;
+ mapif->sendall(buf, 19);
+ return 0;
+}
+
+//Dissolution party notification
+static int mapif_party_broken(int party_id, int flag)
+{
+ unsigned char buf[16];
+ WBUFW(buf, 0) = 0x3826;
+ WBUFL(buf, 2) = party_id;
+ WBUFB(buf, 6) = flag;
+ mapif->sendall(buf, 7);
+ //printf("int_party: broken %d\n",party_id);
+ return 0;
+}
+
+//Remarks in the party
+static int mapif_party_message(int party_id, int account_id, const char *mes, int len, int sfd)
+{
+ unsigned char buf[512];
+ nullpo_ret(mes);
+ WBUFW(buf, 0) = 0x3827;
+ WBUFW(buf, 2) = len + 12;
+ WBUFL(buf, 4) = party_id;
+ WBUFL(buf, 8) = account_id;
+ memcpy(WBUFP(buf, 12), mes, len);
+ mapif->sendallwos(sfd, buf, len + 12);
+ return 0;
+}
+
+// Create Party
+static int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const struct party_member *leader)
+{
+ struct party_data *p;
+
+ nullpo_ret(name);
+ nullpo_ret(leader);
+
+ p = inter_party->create(name, item, item2, leader);
+
+ if (p == NULL) {
+ mapif->party_created(fd, leader->account_id, leader->char_id, NULL);
+ return 0;
+ }
+
+ mapif->party_info(fd, &p->party, 0);
+ mapif->party_created(fd, leader->account_id, leader->char_id, &p->party);
+
+ return 0;
+}
+
+// Party information request
+static void mapif_parse_PartyInfo(int fd, int party_id, int char_id)
+{
+ struct party_data *p;
+ p = inter_party->fromsql(party_id);
+
+ if (p != NULL)
+ mapif->party_info(fd, &p->party, char_id);
+ else
+ mapif->party_noinfo(fd, party_id, char_id);
+}
+
+// Add a player to party request
+static int mapif_parse_PartyAddMember(int fd, int party_id, const struct party_member *member)
+{
+ nullpo_ret(member);
+
+ if (!inter_party->add_member(party_id, member)) {
+ mapif->party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
+ return 0;
+ }
+ mapif->party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
+
+ return 0;
+}
+
+//Party setting change request
+static int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, int exp, int item)
+{
+ inter_party->change_option(party_id, account_id, exp, item, fd);
+ return 0;
+}
+
+//Request leave party
+static int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
+{
+ inter_party->leave(party_id, account_id, char_id);
+ return 0;
+}
+
+// When member goes to other map or levels up.
+static int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv)
+{
+ inter_party->change_map(party_id, account_id, char_id, map, online, lv);
+ return 0;
+}
+
+//Request party dissolution
+static int mapif_parse_BreakParty(int fd, int party_id)
+{
+ inter_party->disband(party_id);
+ return 0;
+}
+
+//Party sending the message
+static int mapif_parse_PartyMessage(int fd, int party_id, int account_id, const char *mes, int len)
+{
+ return mapif->party_message(party_id, account_id, mes, len, fd);
+}
+
+static int mapif_parse_PartyLeaderChange(int fd, int party_id, int account_id, int char_id)
+{
+ if (!inter_party->change_leader(party_id, account_id, char_id))
+ return 0;
+ return 1;
+}
+
+static int mapif_pet_created(int fd, int account_id, struct s_pet *p)
+{
+ WFIFOHEAD(fd, 12);
+ WFIFOW(fd, 0) = 0x3880;
+ WFIFOL(fd, 2) = account_id;
+ if (p != NULL){
+ WFIFOW(fd, 6) = p->class_;
+ WFIFOL(fd, 8) = p->pet_id;
+ ShowInfo("int_pet: created pet %d - %s\n", p->pet_id, p->name);
+ } else {
+ WFIFOB(fd, 6) = 0;
+ WFIFOL(fd, 8) = 0;
+ }
+ WFIFOSET(fd, 12);
+
+ return 0;
+}
+
+static int mapif_pet_info(int fd, int account_id, struct s_pet *p)
+{
+ nullpo_ret(p);
+ WFIFOHEAD(fd, sizeof(struct s_pet) + 9);
+ WFIFOW(fd, 0) = 0x3881;
+ WFIFOW(fd, 2) = sizeof(struct s_pet) + 9;
+ WFIFOL(fd, 4) = account_id;
+ WFIFOB(fd, 8) = 0;
+ memcpy(WFIFOP(fd, 9), p, sizeof(struct s_pet));
+ WFIFOSET(fd, WFIFOW(fd, 2));
+
+ return 0;
+}
+
+static int mapif_pet_noinfo(int fd, int account_id)
+{
+ WFIFOHEAD(fd, sizeof(struct s_pet) + 9);
+ WFIFOW(fd, 0) = 0x3881;
+ WFIFOW(fd, 2) = sizeof(struct s_pet) + 9;
+ WFIFOL(fd, 4) = account_id;
+ WFIFOB(fd, 8) = 1;
+ memset(WFIFOP(fd, 9), 0, sizeof(struct s_pet));
+ WFIFOSET(fd, WFIFOW(fd, 2));
+
+ return 0;
+}
+
+static int mapif_save_pet_ack(int fd, int account_id, int flag)
+{
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3882;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOB(fd, 6) = flag;
+ WFIFOSET(fd, 7);
+
+ return 0;
+}
+
+static int mapif_delete_pet_ack(int fd, int flag)
+{
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x3883;
+ WFIFOB(fd, 2) = flag;
+ WFIFOSET(fd, 3);
+
+ return 0;
+}
+
+static int mapif_save_pet(int fd, int account_id, const struct s_pet *data)
+{
+ //here process pet save request.
+ int len;
+ nullpo_ret(data);
+ RFIFOHEAD(fd);
+ len = RFIFOW(fd, 2);
+ if (sizeof(struct s_pet) != len-8) {
+ ShowError("inter pet: data size mismatch: %d != %"PRIuS"\n", len-8, sizeof(struct s_pet));
+ return 0;
+ }
+
+ inter_pet->tosql(data);
+ mapif->save_pet_ack(fd, account_id, 0);
+
+ return 0;
+}
+
+static int mapif_delete_pet(int fd, int pet_id)
+{
+ mapif->delete_pet_ack(fd, inter_pet->delete_(pet_id));
+
+ return 0;
+}
+
+static int mapif_parse_CreatePet(int fd)
+{
+ int account_id;
+ struct s_pet *pet;
+
+ RFIFOHEAD(fd);
+ account_id = RFIFOL(fd, 2);
+ pet = inter_pet->create(account_id,
+ RFIFOL(fd, 6),
+ RFIFOW(fd, 10),
+ RFIFOW(fd, 12),
+ RFIFOL(fd, 14),
+ RFIFOL(fd, 18),
+ RFIFOW(fd, 22),
+ RFIFOW(fd, 24),
+ RFIFOB(fd, 26),
+ RFIFOB(fd, 27),
+ RFIFOP(fd, 28));
+
+ if (pet != NULL)
+ mapif->pet_created(fd, account_id, pet);
+ else
+ mapif->pet_created(fd, account_id, NULL);
+
+ return 0;
+}
+
+static int mapif_parse_LoadPet(int fd)
+{
+ int account_id;
+ struct s_pet *pet;
+
+ RFIFOHEAD(fd);
+ account_id = RFIFOL(fd, 2);
+ pet = inter_pet->load(account_id, RFIFOL(fd, 6), RFIFOL(fd, 10));
+
+ if (pet != NULL)
+ mapif->pet_info(fd, account_id, pet);
+ else
+ mapif->pet_noinfo(fd, account_id);
+ return 0;
+}
+
+static int mapif_parse_SavePet(int fd)
+{
+ RFIFOHEAD(fd);
+ mapif->save_pet(fd, RFIFOL(fd, 4), RFIFOP(fd, 8));
+ return 0;
+}
+
+static int mapif_parse_DeletePet(int fd)
+{
+ RFIFOHEAD(fd);
+ mapif->delete_pet(fd, RFIFOL(fd, 2));
+ return 0;
+}
+
+static void mapif_quest_save_ack(int fd, int char_id, bool success)
+{
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3861;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOB(fd, 6) = success ? 1 : 0;
+ WFIFOSET(fd, 7);
+}
+
+/**
+ * Handles the save request from mapserver for a character's questlog.
+ *
+ * Received quests are saved, and an ack is sent back to the map server.
+ *
+ * @see inter_parse_frommap
+ */
+static int mapif_parse_quest_save(int fd)
+{
+ int num = (RFIFOW(fd, 2) - 8) / sizeof(struct quest);
+ int char_id = RFIFOL(fd, 4);
+ const struct quest *qd = NULL;
+ bool success;
+
+ if (num > 0)
+ qd = RFIFOP(fd,8);
+
+ success = inter_quest->save(char_id, qd, num);
+
+ // Send ack
+ mapif->quest_save_ack(fd, char_id, success);
+
+ return 0;
+}
+
+static void mapif_send_quests(int fd, int char_id, struct quest *tmp_questlog, int num_quests)
+{
+ WFIFOHEAD(fd,num_quests*sizeof(struct quest) + 8);
+ WFIFOW(fd, 0) = 0x3860;
+ WFIFOW(fd, 2) = num_quests*sizeof(struct quest) + 8;
+ WFIFOL(fd, 4) = char_id;
+
+ if (num_quests > 0) {
+ nullpo_retv(tmp_questlog);
+ memcpy(WFIFOP(fd, 8), tmp_questlog, sizeof(struct quest) * num_quests);
+ }
+
+ WFIFOSET(fd, num_quests * sizeof(struct quest) + 8);
+}
+
+/**
+ * Sends questlog to the map server
+ *
+ * Note: Completed quests (state == Q_COMPLETE) are guaranteed to be sent last
+ * and the map server relies on this behavior (once the first Q_COMPLETE quest,
+ * all of them are considered to be Q_COMPLETE)
+ *
+ * @see inter_parse_frommap
+ */
+static int mapif_parse_quest_load(int fd)
+{
+ int char_id = RFIFOL(fd,2);
+ struct quest *tmp_questlog = NULL;
+ int num_quests;
+
+ tmp_questlog = inter_quest->fromsql(char_id, &num_quests);
+ mapif->send_quests(fd, char_id, tmp_questlog, num_quests);
+
+ if (tmp_questlog != NULL)
+ aFree(tmp_questlog);
+
+ return 0;
+}
+
+/* RoDEX */
+
+/*==========================================
+ * Inbox Request
+ *------------------------------------------*/
+static void mapif_parse_rodex_requestinbox(int fd)
+{
+ int count;
+ int char_id = RFIFOL(fd,2);
+ int account_id = RFIFOL(fd, 6);
+ int8 flag = RFIFOB(fd, 10);
+ int8 opentype = RFIFOB(fd, 11);
+ int64 mail_id = RFIFOQ(fd, 12);
+ struct rodex_maillist mails = { 0 };
+
+ VECTOR_INIT(mails);
+ if (flag == 0)
+ 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, mail_id, &mails);
+ VECTOR_CLEAR(mails);
+}
+
+static 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 - 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 = 24, j, size, limit;
+ int to_send = count - sent;
+ bool is_last = true;
+
+ if (to_send <= per_packet) {
+ size = to_send * sizeof(struct rodex_message) + 24;
+ limit = to_send;
+ is_last = true;
+ } else {
+ limit = min(to_send, per_packet);
+ if (limit != to_send) {
+ is_last = false;
+ }
+ size = limit * sizeof(struct rodex_message) + 24;
+ }
+
+ WFIFOHEAD(fd, size);
+ WFIFOW(fd, 0) = 0x3895;
+ WFIFOW(fd, 2) = size;
+ WFIFOL(fd, 4) = char_id;
+ WFIFOB(fd, 8) = opentype;
+ WFIFOB(fd, 9) = flag;
+ WFIFOB(fd, 10) = is_last;
+ 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);
+}
+
+/*==========================================
+ * Checks if there are new mails
+ *------------------------------------------*/
+static void mapif_parse_rodex_checkhasnew(int fd)
+{
+ int char_id = RFIFOL(fd, 2);
+ int account_id = RFIFOL(fd, 6);
+ bool has_new;
+
+ Assert_retv(account_id >= START_ACCOUNT_NUM && account_id <= END_ACCOUNT_NUM);
+ Assert_retv(char_id >= START_CHAR_NUM);
+
+ has_new = inter_rodex->hasnew(char_id, account_id);
+ mapif->rodex_sendhasnew(fd, char_id, has_new);
+}
+
+static void mapif_rodex_sendhasnew(int fd, int char_id, bool has_new)
+{
+ Assert_retv(char_id > 0);
+
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3896;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOB(fd, 6) = has_new;
+ WFIFOSET(fd, 7);
+}
+
+/*==========================================
+ * Update/Delete mail
+ *------------------------------------------*/
+static void mapif_parse_rodex_updatemail(int fd)
+{
+ int64 mail_id = RFIFOL(fd, 2);
+ int8 flag = RFIFOB(fd, 10);
+
+ inter_rodex->updatemail(mail_id, flag);
+}
+
+/*==========================================
+ * Send Mail
+ *------------------------------------------*/
+static void mapif_parse_rodex_send(int fd)
+{
+ struct rodex_message msg = { 0 };
+
+ if (RFIFOW(fd,2) != 4 + sizeof(struct rodex_message))
+ return;
+
+ memcpy(&msg, RFIFOP(fd,4), sizeof(struct rodex_message));
+ if (msg.receiver_id > 0 || msg.receiver_accountid > 0)
+ msg.id = inter_rodex->savemessage(&msg);
+
+ mapif->rodex_send(fd, msg.sender_id, msg.receiver_id, msg.receiver_accountid, msg.id > 0 ? true : false);
+}
+
+static void mapif_rodex_send(int fd, int sender_id, int receiver_id, int receiver_accountid, bool result)
+{
+ Assert_retv(sender_id >= 0);
+ Assert_retv(receiver_id + receiver_accountid > 0);
+
+ WFIFOHEAD(fd,15);
+ WFIFOW(fd,0) = 0x3897;
+ WFIFOL(fd,2) = sender_id;
+ WFIFOL(fd,6) = receiver_id;
+ WFIFOL(fd,10) = receiver_accountid;
+ WFIFOB(fd,14) = result;
+ WFIFOSET(fd,15);
+}
+
+/*------------------------------------------
+ * Check Player
+ *------------------------------------------*/
+static void mapif_parse_rodex_checkname(int fd)
+{
+ int reqchar_id = RFIFOL(fd, 2);
+ char name[NAME_LENGTH];
+ int target_char_id, target_level;
+ short target_class;
+
+ safestrncpy(name, RFIFOP(fd, 6), NAME_LENGTH);
+
+ if (inter_rodex->checkname(name, &target_char_id, &target_class, &target_level) == true)
+ mapif->rodex_checkname(fd, reqchar_id, target_char_id, target_class, target_level, name);
+ else
+ mapif->rodex_checkname(fd, reqchar_id, 0, 0, 0, name);
+}
+
+static void mapif_rodex_checkname(int fd, int reqchar_id, int target_char_id, short target_class, int target_level, char *name)
+{
+ nullpo_retv(name);
+ Assert_retv(reqchar_id > 0);
+ Assert_retv(target_char_id >= 0);
+
+ WFIFOHEAD(fd, 16 + NAME_LENGTH);
+ WFIFOW(fd, 0) = 0x3898;
+ WFIFOL(fd, 2) = reqchar_id;
+ WFIFOL(fd, 6) = target_char_id;
+ WFIFOW(fd, 10) = target_class;
+ WFIFOL(fd, 12) = target_level;
+ safestrncpy(WFIFOP(fd, 16), name, NAME_LENGTH);
+ WFIFOSET(fd, 16 + NAME_LENGTH);
+}
+
+static int mapif_load_guild_storage(int fd, int account_id, int guild_id, char flag)
+{
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id)) {
+ Sql_ShowDebug(inter->sql_handle);
+ } else if (SQL->NumRows(inter->sql_handle) > 0) {
+ // guild exists
+ WFIFOHEAD(fd, sizeof(struct guild_storage) + 13);
+ WFIFOW(fd, 0) = 0x3818;
+ WFIFOW(fd, 2) = sizeof(struct guild_storage)+13;
+ WFIFOL(fd, 4) = account_id;
+ WFIFOL(fd, 8) = guild_id;
+ WFIFOB(fd, 12) = flag; //1 open storage, 0 don't open
+ inter_storage->guild_storage_fromsql(guild_id, WFIFOP(fd, 13));
+ WFIFOSET(fd, WFIFOW(fd, 2));
+ return 0;
+ }
+ // guild does not exist
+ SQL->FreeResult(inter->sql_handle);
+ WFIFOHEAD(fd, 12);
+ WFIFOW(fd, 0) = 0x3818;
+ WFIFOW(fd, 2) = 12;
+ WFIFOL(fd, 4) = account_id;
+ WFIFOL(fd, 8) = 0;
+ WFIFOSET(fd, 12);
+ return 0;
+}
+
+static int mapif_save_guild_storage_ack(int fd, int account_id, int guild_id, int fail)
+{
+ WFIFOHEAD(fd, 11);
+ WFIFOW(fd, 0) = 0x3819;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOL(fd, 6) = guild_id;
+ WFIFOB(fd, 10) = fail;
+ WFIFOSET(fd, 11);
+ return 0;
+}
+
+/**
+ * Loads the account storage and send to the map server.
+ * @packet 0x3805 [out] <account_id>.L <struct item[]>.P
+ * @param fd [in] file/socket descriptor.
+ * @param account_id [in] account id of the session.
+ * @return 1 on success, 0 on failure.
+ */
+static int mapif_account_storage_load(int fd, int account_id)
+{
+ struct storage_data stor = { 0 };
+ int count = 0, i = 0, len = 0;
+
+ Assert_ret(account_id > 0);
+
+ VECTOR_INIT(stor.item);
+ count = inter_storage->fromsql(account_id, &stor);
+
+ len = 8 + count * sizeof(struct item);
+
+ WFIFOHEAD(fd, len);
+ WFIFOW(fd, 0) = 0x3805;
+ WFIFOW(fd, 2) = (uint16) len;
+ WFIFOL(fd, 4) = account_id;
+ for (i = 0; i < count; i++)
+ memcpy(WFIFOP(fd, 8 + i * sizeof(struct item)), &VECTOR_INDEX(stor.item, i), sizeof(struct item));
+ WFIFOSET(fd, len);
+
+ VECTOR_CLEAR(stor.item);
+
+ return 1;
+}
+
+/**
+ * Parses account storage load request from map server.
+ * @packet 0x3010 [in] <account_id>.L
+ * @param fd [in] file/socket descriptor
+ * @return 1 on success, 0 on failure.
+ */
+static int mapif_parse_AccountStorageLoad(int fd)
+{
+ int account_id = RFIFOL(fd, 2);
+
+ Assert_ret(fd > 0);
+ Assert_ret(account_id > 0);
+
+ mapif->account_storage_load(fd, account_id);
+
+ return 1;
+}
+
+/**
+ * Parses an account storage save request from the map server.
+ * @packet 0x3011 [in] <packet_len>.W <account_id>.L <struct item[]>.P
+ * @param fd [in] file/socket descriptor.
+ * @return 1 on success, 0 on failure.
+ */
+static int mapif_parse_AccountStorageSave(int fd)
+{
+ int payload_size = RFIFOW(fd, 2) - 8, account_id = RFIFOL(fd, 4);
+ int i = 0, count = 0;
+ struct storage_data p_stor = { 0 };
+
+ Assert_ret(fd > 0);
+ Assert_ret(account_id > 0);
+
+ count = payload_size/sizeof(struct item);
+
+ VECTOR_INIT(p_stor.item);
+
+ if (count > 0) {
+ VECTOR_ENSURE(p_stor.item, count, 1);
+
+ for (i = 0; i < count; i++) {
+ const struct item *it = RFIFOP(fd, 8 + i * sizeof(struct item));
+
+ VECTOR_PUSH(p_stor.item, *it);
+ }
+
+ p_stor.aggregate = count;
+ }
+
+ inter_storage->tosql(account_id, &p_stor);
+
+ VECTOR_CLEAR(p_stor.item);
+
+ mapif->sAccountStorageSaveAck(fd, account_id, true);
+
+ return 1;
+}
+
+/**
+ * Sends an acknowledgement for the save
+ * status of the account storage.
+ * @packet 0x3808 [out] <account_id>.L <save_flag>.B
+ * @param fd [in] File/Socket Descriptor.
+ * @param account_id [in] Account ID of the storage in question.
+ * @param flag [in] Save flag, true for success and false for failure.
+ */
+static void mapif_send_AccountStorageSaveAck(int fd, int account_id, bool flag)
+{
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3808;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOB(fd, 6) = flag ? 1 : 0;
+ WFIFOSET(fd, 7);
+}
+
+static int mapif_parse_LoadGuildStorage(int fd)
+{
+ RFIFOHEAD(fd);
+
+ mapif->load_guild_storage(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), 1);
+
+ return 0;
+}
+
+static int mapif_parse_SaveGuildStorage(int fd)
+{
+ int guild_id;
+ int len;
+
+ RFIFOHEAD(fd);
+ guild_id = RFIFOL(fd, 8);
+ len = RFIFOW(fd, 2);
+
+ if (sizeof(struct guild_storage) != len - 12) {
+ ShowError("inter storage: data size mismatch: %d != %"PRIuS"\n", len - 12, sizeof(struct guild_storage));
+ } else if (inter_storage->guild_storage_tosql(guild_id, RFIFOP(fd, 12))) {
+ mapif->save_guild_storage_ack(fd, RFIFOL(fd, 4), guild_id, 0);
+ return 0;
+ }
+ mapif->save_guild_storage_ack(fd, RFIFOL(fd, 4), guild_id, 1);
+
+ return 0;
+}
+
+static int mapif_itembound_ack(int fd, int aid, int guild_id)
+{
+#ifdef GP_BOUND_ITEMS
+ WFIFOHEAD(fd, 8);
+ WFIFOW(fd, 0) = 0x3856;
+ WFIFOL(fd, 2) = aid;/* the value is not being used, drop? */
+ WFIFOW(fd, 6) = guild_id;
+ WFIFOSET(fd, 8);
+#endif
+ return 0;
+}
+
+static void mapif_parse_ItemBoundRetrieve(int fd)
+{
+#ifdef GP_BOUND_ITEMS
+ int char_id = RFIFOL(fd, 2);
+ int account_id = RFIFOL(fd, 6);
+ int guild_id = RFIFOW(fd, 10);
+
+ inter_storage->retrieve_bound_items(char_id, account_id, guild_id);
+
+ //Finally reload storage and tell map we're done
+ mapif->load_guild_storage(fd, account_id, guild_id, 0);
+
+ // If character is logged in char, disconnect
+ chr->disconnect_player(account_id);
+#endif // GP_BOUND_ITEMS
+
+ /* tell map server the operation is over and it can unlock the storage */
+ mapif->itembound_ack(fd, RFIFOL(fd, 6), RFIFOW(fd, 10));
+}
+
+static void mapif_parse_accinfo(int fd)
+{
+ char query[NAME_LENGTH];
+ int u_fd = RFIFOL(fd, 2), aid = RFIFOL(fd, 6), castergroup = RFIFOL(fd, 10);
+
+ safestrncpy(query, RFIFOP(fd, 14), NAME_LENGTH);
+
+ inter->accinfo(u_fd, aid, castergroup, query, fd);
+}
+
+// broadcast sending
+static int mapif_broadcast(const unsigned char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd)
+{
+ unsigned char *buf = (unsigned char*)aMalloc((len)*sizeof(unsigned char));
+
+ nullpo_ret(mes);
+ Assert_ret(len >= 16);
+ WBUFW(buf, 0) = 0x3800;
+ WBUFW(buf, 2) = len;
+ WBUFL(buf, 4) = fontColor;
+ WBUFW(buf, 8) = fontType;
+ WBUFW(buf, 10) = fontSize;
+ WBUFW(buf, 12) = fontAlign;
+ WBUFW(buf, 14) = fontY;
+ memcpy(WBUFP(buf, 16), mes, len - 16);
+ mapif->sendallwos(sfd, buf, len);
+
+ aFree(buf);
+ return 0;
+}
+
+// Wis sending
+static int mapif_wis_message(struct WisData *wd)
+{
+ unsigned char buf[2048];
+ nullpo_ret(wd);
+ //if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex]
+ if (wd->len < 0)
+ wd->len = 0;
+ if (wd->len >= (int)sizeof(wd->msg) - 1)
+ wd->len = (int)sizeof(wd->msg) - 1;
+
+ WBUFW(buf, 0) = 0x3801;
+ WBUFW(buf, 2) = 56 + wd->len;
+ WBUFL(buf, 4) = wd->id;
+ memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH);
+ memcpy(WBUFP(buf, 32), wd->dst, NAME_LENGTH);
+ memcpy(WBUFP(buf, 56), wd->msg, wd->len);
+ wd->count = mapif->sendall(buf, WBUFW(buf, 2));
+
+ return 0;
+}
+
+static void mapif_wis_response(int fd, const unsigned char *src, int flag)
+{
+ unsigned char buf[27];
+ nullpo_retv(src);
+ WBUFW(buf, 0) = 0x3802;
+ memcpy(WBUFP(buf, 2), src, 24);
+ WBUFB(buf, 26) = flag;
+ mapif->send(fd, buf, 27);
+}
+
+// Wis sending result
+static int mapif_wis_end(struct WisData *wd, int flag)
+{
+ nullpo_ret(wd);
+ mapif->wis_response(wd->fd, wd->src, flag);
+ return 0;
+}
+
+#if 0
+// Account registry transfer to map-server
+static void mapif_account_reg(int fd, unsigned char *src)
+{
+ nullpo_retv(src);
+ WBUFW(src, 0) = 0x3804; //NOTE: writing to RFIFO
+ mapif->sendallwos(fd, src, WBUFW(src, 2));
+}
+#endif // 0
+
+// Send the requested account_reg
+static int mapif_account_reg_reply(int fd,int account_id,int char_id, int type)
+{
+ inter->accreg_fromsql(account_id, char_id, fd, type);
+ return 0;
+}
+
+//Request to kick char from a certain map server. [Skotlex]
+static int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason)
+{
+ if (fd < 0)
+ return -1;
+
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x2b1f;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOB(fd, 6) = reason;
+ WFIFOSET(fd, 7);
+ return 0;
+}
+
+// broadcast sending
+static int mapif_parse_broadcast(int fd)
+{
+ mapif->broadcast(RFIFOP(fd, 16), RFIFOW(fd, 2), RFIFOL(fd, 4), RFIFOW(fd, 8), RFIFOW(fd, 10), RFIFOW(fd, 12), RFIFOW(fd, 14), fd);
+ return 0;
+}
+
+// Wisp/page request to send
+static int mapif_parse_WisRequest(int fd)
+{
+ struct WisData* wd;
+ char name[NAME_LENGTH];
+ char *data;
+ size_t len;
+
+ if (fd <= 0) // check if we have a valid fd
+ return 0;
+
+ if (RFIFOW(fd, 2) - 52 >= sizeof(wd->msg)) {
+ ShowWarning("inter: Wis message size too long.\n");
+ return 0;
+ } else if (RFIFOW(fd, 2) - 52 <= 0) { // normally, impossible, but who knows...
+ ShowError("inter: Wis message doesn't exist.\n");
+ return 0;
+ }
+
+ safestrncpy(name, RFIFOP(fd, 28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
+
+ // search if character exists before to ask all map-servers
+ if (!chr->name_exists(name, NULL)) {
+ mapif->wis_response(fd, RFIFOP(fd, 4), 1);
+ } else {
+ // Character exists. So, ask all map-servers
+
+ // to be sure of the correct name, rewrite it
+ SQL->GetData(inter->sql_handle, 0, &data, &len);
+ memset(name, 0, NAME_LENGTH);
+ memcpy(name, data, min(len, NAME_LENGTH));
+ // if source is destination, don't ask other servers.
+ if (strncmp(RFIFOP(fd, 4), name, NAME_LENGTH) == 0) {
+ mapif->wis_response(fd, RFIFOP(fd, 4), 1);
+ } else {
+ wd = inter->add_wisdata(fd, RFIFOP(fd, 4), RFIFOP(fd, 28), RFIFOP(fd, 52), RFIFOW(fd, 2) - 52);
+ mapif->wis_message(wd);
+ }
+ }
+
+ SQL->FreeResult(inter->sql_handle);
+ return 0;
+}
+
+// Wisp/page transmission result
+static int mapif_parse_WisReply(int fd)
+{
+ int id, flag;
+ struct WisData *wd;
+
+ id = RFIFOL(fd,2);
+ flag = RFIFOB(fd,6);
+ wd = inter->get_wisdata(id);
+ if (wd == NULL)
+ return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
+
+ if ((--wd->count) <= 0 || flag != 1) {
+ mapif->wis_end(wd, flag); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target
+ inter->remove_wisdata(id);
+ }
+
+ return 0;
+}
+
+// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
+static int mapif_parse_WisToGM(int fd)
+{
+ unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
+
+ memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); // Message contains the NUL terminator (see intif_wis_message_to_gm())
+ WBUFW(buf, 0) = 0x3803;
+ mapif->sendall(buf, RFIFOW(fd,2));
+
+ return 0;
+}
+
+// Save account_reg into sql (type=2)
+static int mapif_parse_Registry(int fd)
+{
+ int account_id = RFIFOL(fd, 4), char_id = RFIFOL(fd, 8), count = RFIFOW(fd, 12);
+
+ if (count != 0) {
+ int cursor = 14, i;
+ char key[SCRIPT_VARNAME_LENGTH+1], sval[254];
+ bool isLoginActive = sockt->session_is_active(chr->login_fd);
+
+ if (isLoginActive)
+ chr->global_accreg_to_login_start(account_id, char_id);
+
+ for (i = 0; i < count; i++) {
+ unsigned int index;
+ int len = RFIFOB(fd, cursor);
+ safestrncpy(key, RFIFOP(fd, cursor + 1), min((int)sizeof(key), len));
+ cursor += len + 1;
+
+ index = RFIFOL(fd, cursor);
+ cursor += 4;
+
+ switch (RFIFOB(fd, cursor++)) {
+ /* int */
+ case 0:
+ inter->savereg(account_id, char_id, key, index, RFIFOL(fd, cursor), false);
+ cursor += 4;
+ break;
+ case 1:
+ inter->savereg(account_id, char_id, key, index, 0, false);
+ break;
+ /* str */
+ case 2:
+ len = RFIFOB(fd, cursor);
+ safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len));
+ cursor += len + 1;
+ inter->savereg(account_id, char_id, key, index, (intptr_t)sval, true);
+ break;
+ case 3:
+ inter->savereg(account_id, char_id, key, index, 0, true);
+ break;
+ default:
+ ShowError("mapif->parse_Registry: unknown type %d\n", RFIFOB(fd, cursor - 1));
+ return 1;
+ }
+ }
+
+ if (isLoginActive)
+ chr->global_accreg_to_login_send();
+ }
+ return 0;
+}
+
+// Request the value of all registries.
+static int mapif_parse_RegistryRequest(int fd)
+{
+ //Load Char Registry
+ if (RFIFOB(fd, 12))
+ mapif->account_reg_reply(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), 3); // 3: char reg
+ //Load Account Registry
+ if (RFIFOB(fd, 11) != 0)
+ mapif->account_reg_reply(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), 2); // 2: account reg
+ //Ask Login Server for Account2 values.
+ if (RFIFOB(fd, 10) != 0)
+ chr->request_accreg2(RFIFOL(fd, 2), RFIFOL(fd, 6));
+ return 1;
+}
+
+static void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, const char *const name)
+{
+ nullpo_retv(name);
+ WFIFOHEAD(fd, NAME_LENGTH+13);
+ WFIFOW(fd, 0) = 0x3806;
+ WFIFOL(fd, 2) = account_id;
+ WFIFOL(fd, 6) = char_id;
+ WFIFOB(fd, 10) = type;
+ WFIFOB(fd, 11) = flag;
+ memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
+ WFIFOSET(fd, NAME_LENGTH + 13);
+}
+
+static int mapif_parse_NameChangeRequest(int fd)
+{
+ int account_id, char_id, type;
+ const char *name;
+ int i;
+
+ account_id = RFIFOL(fd, 2);
+ char_id = RFIFOL(fd, 6);
+ type = RFIFOB(fd, 10);
+ name = RFIFOP(fd, 11);
+
+ // Check Authorized letters/symbols in the name
+ if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorized
+ for (i = 0; i < NAME_LENGTH && name[i]; i++)
+ if (strchr(char_name_letters, name[i]) == NULL) {
+ mapif->namechange_ack(fd, account_id, char_id, type, 0, name);
+ return 0;
+ }
+ } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
+ for (i = 0; i < NAME_LENGTH && name[i]; i++)
+ if (strchr(char_name_letters, name[i]) != NULL) {
+ mapif->namechange_ack(fd, account_id, char_id, type, 0, name);
+ return 0;
+ }
+ }
+ //TODO: type holds the type of object to rename.
+ //If it were a player, it needs to have the guild information and db information
+ //updated here, because changing it on the map won't make it be saved [Skotlex]
+
+ //name allowed.
+ mapif->namechange_ack(fd, account_id, char_id, type, 1, name);
+ return 0;
+}
+
+// Clan System
+static 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;
+}
+
+static 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;
+}
+
+// Achievement System
+/**
+ * Parse achievement load request from the map server
+ * @param[in] fd socket descriptor.
+ */
+static void mapif_parse_load_achievements(int fd)
+{
+ int char_id = 0;
+
+ /* Read received information from map-server. */
+ RFIFOHEAD(fd);
+ char_id = RFIFOL(fd, 2);
+
+ /* Load and send achievements to map */
+ mapif->achievement_load(fd, char_id);
+}
+
+/**
+ * Loads achievements and sends to the map server.
+ * @param[in] fd socket descriptor
+ * @param[in] char_id character Id.
+ */
+static void mapif_achievement_load(int fd, int char_id)
+{
+ struct char_achievements *cp = NULL;
+
+ /* Ensure data exists */
+ cp = idb_ensure(inter_achievement->char_achievements, char_id, inter_achievement->ensure_char_achievements);
+
+ /* Load storage for char-server. */
+ inter_achievement->fromsql(char_id, cp);
+
+ /* Send Achievements to map server. */
+ mapif->sAchievementsToMap(fd, char_id, cp);
+}
+
+/**
+ * Sends achievement data of a character to the map server.
+ * @packet[out] 0x3810 <packet_id>.W <payload_size>.W <char_id>.L <char_achievements[]>.P
+ * @param[in] fd socket descriptor.
+ * @param[in] char_id Character ID.
+ * @param[in] cp Pointer to character's achievement data vector.
+ */
+static void mapif_send_achievements_to_map(int fd, int char_id, const struct char_achievements *cp)
+{
+ int i = 0;
+ int data_size = 0;
+
+ nullpo_retv(cp);
+
+ data_size = sizeof(struct achievement) * VECTOR_LENGTH(*cp);
+
+STATIC_ASSERT((sizeof(struct achievement) * MAX_ACHIEVEMENT_DB + 8 <= UINT16_MAX),
+ "The achievements data can potentially be larger than the maximum packet size. This may cause errors at run-time.");
+
+ /* Send to the map server. */
+ WFIFOHEAD(fd, (8 + data_size));
+ WFIFOW(fd, 0) = 0x3810;
+ WFIFOW(fd, 2) = (8 + data_size);
+ WFIFOL(fd, 4) = char_id;
+ for (i = 0; i < VECTOR_LENGTH(*cp); i++)
+ memcpy(WFIFOP(fd, 8 + i * sizeof(struct achievement)), &VECTOR_INDEX(*cp, i), sizeof(struct achievement));
+ WFIFOSET(fd, 8 + data_size);
+}
+
+/**
+ * Handles achievement request and saves data from map server.
+ * @packet[in] 0x3013 <packet_size>.W <char_id>.L <char_achievement>.P
+ * @param[in] fd session socket descriptor.
+ */
+static void mapif_parse_save_achievements(int fd)
+{
+ int size = 0, char_id = 0, payload_count = 0, i = 0;
+ struct char_achievements p = { 0 };
+
+ RFIFOHEAD(fd);
+ size = RFIFOW(fd, 2);
+ char_id = RFIFOL(fd, 4);
+
+ payload_count = (size - 8) / sizeof(struct achievement);
+
+ VECTOR_INIT(p);
+ VECTOR_ENSURE(p, payload_count, 1);
+
+ for (i = 0; i < payload_count; i++) {
+ struct achievement ach = { 0 };
+ memcpy(&ach, RFIFOP(fd, 8 + i * sizeof(struct achievement)), sizeof(struct achievement));
+ VECTOR_PUSH(p, ach);
+ }
+
+ mapif->achievement_save(char_id, &p);
+
+ VECTOR_CLEAR(p);
+}
+
+/**
+ * Handles inter-server achievement db ensuring
+ * and saves current achievements to sql.
+ * @param[in] char_id character identifier.
+ * @param[out] p pointer to character achievements vector.
+ */
+static void mapif_achievement_save(int char_id, struct char_achievements *p)
+{
+ struct char_achievements *cp = NULL;
+
+ nullpo_retv(p);
+
+ /* Get loaded achievements. */
+ cp = idb_ensure(inter_achievement->char_achievements, char_id, inter_achievement->ensure_char_achievements);
+
+ if (VECTOR_LENGTH(*p)) /* Save current achievements. */
+ inter_achievement->tosql(char_id, cp, p);
+}
+
+void mapif_defaults(void)
+{
mapif = &mapif_s;
mapif->ban = mapif_ban;
@@ -224,6 +2476,11 @@ void mapif_defaults(void) {
mapif->sendallwos = mapif_sendallwos;
mapif->send = mapif_send;
mapif->send_users_count = mapif_send_users_count;
+ mapif->pLoadAchievements = mapif_parse_load_achievements;
+ mapif->sAchievementsToMap = mapif_send_achievements_to_map;
+ mapif->pSaveAchievements = mapif_parse_save_achievements;
+ mapif->achievement_load = mapif_achievement_load;
+ mapif->achievement_save = mapif_achievement_save;
mapif->auction_message = mapif_auction_message;
mapif->auction_sendlist = mapif_auction_sendlist;
mapif->parse_auction_requestlist = mapif_parse_auction_requestlist;
@@ -235,10 +2492,6 @@ void mapif_defaults(void) {
mapif->parse_auction_close = mapif_parse_auction_close;
mapif->auction_bid = mapif_auction_bid;
mapif->parse_auction_bid = mapif_parse_auction_bid;
- mapif->elemental_create = mapif_elemental_create;
- mapif->elemental_save = mapif_elemental_save;
- mapif->elemental_load = mapif_elemental_load;
- mapif->elemental_delete = mapif_elemental_delete;
mapif->elemental_send = mapif_elemental_send;
mapif->parse_elemental_create = mapif_parse_elemental_create;
mapif->parse_elemental_load = mapif_parse_elemental_load;
@@ -274,7 +2527,6 @@ void mapif_defaults(void) {
mapif->parse_GuildMemberInfoChange = mapif_parse_GuildMemberInfoChange;
mapif->parse_GuildPosition = mapif_parse_GuildPosition;
mapif->parse_GuildSkillUp = mapif_parse_GuildSkillUp;
- mapif->parse_GuildDeleteAlliance = mapif_parse_GuildDeleteAlliance;
mapif->parse_GuildAlliance = mapif_parse_GuildAlliance;
mapif->parse_GuildNotice = mapif_parse_GuildNotice;
mapif->parse_GuildEmblem = mapif_parse_GuildEmblem;
@@ -286,11 +2538,6 @@ void mapif_defaults(void) {
mapif->homunculus_loaded = mapif_homunculus_loaded;
mapif->homunculus_saved = mapif_homunculus_saved;
mapif->homunculus_renamed = mapif_homunculus_renamed;
- mapif->homunculus_create = mapif_homunculus_create;
- mapif->homunculus_save = mapif_homunculus_save;
- mapif->homunculus_load = mapif_homunculus_load;
- mapif->homunculus_delete = mapif_homunculus_delete;
- mapif->homunculus_rename = mapif_homunculus_rename;
mapif->parse_homunculus_create = mapif_parse_homunculus_create;
mapif->parse_homunculus_delete = mapif_parse_homunculus_delete;
mapif->parse_homunculus_load = mapif_parse_homunculus_load;
@@ -300,7 +2547,6 @@ void mapif_defaults(void) {
mapif->parse_mail_requestinbox = mapif_parse_mail_requestinbox;
mapif->parse_mail_read = mapif_parse_mail_read;
mapif->mail_sendattach = mapif_mail_sendattach;
- mapif->mail_getattach = mapif_mail_getattach;
mapif->parse_mail_getattach = mapif_parse_mail_getattach;
mapif->mail_delete = mapif_mail_delete;
mapif->parse_mail_delete = mapif_parse_mail_delete;
@@ -309,10 +2555,6 @@ void mapif_defaults(void) {
mapif->parse_mail_return = mapif_parse_mail_return;
mapif->mail_send = mapif_mail_send;
mapif->parse_mail_send = mapif_parse_mail_send;
- mapif->mercenary_create = mapif_mercenary_create;
- mapif->mercenary_save = mapif_mercenary_save;
- mapif->mercenary_load = mapif_mercenary_load;
- mapif->mercenary_delete = mapif_mercenary_delete;
mapif->mercenary_send = mapif_mercenary_send;
mapif->parse_mercenary_create = mapif_parse_mercenary_create;
mapif->parse_mercenary_load = mapif_parse_mercenary_load;
@@ -343,31 +2585,37 @@ void mapif_defaults(void) {
mapif->pet_noinfo = mapif_pet_noinfo;
mapif->save_pet_ack = mapif_save_pet_ack;
mapif->delete_pet_ack = mapif_delete_pet_ack;
- mapif->create_pet = mapif_create_pet;
- mapif->load_pet = mapif_load_pet;
mapif->save_pet = mapif_save_pet;
mapif->delete_pet = mapif_delete_pet;
mapif->parse_CreatePet = mapif_parse_CreatePet;
mapif->parse_LoadPet = mapif_parse_LoadPet;
mapif->parse_SavePet = mapif_parse_SavePet;
mapif->parse_DeletePet = mapif_parse_DeletePet;
- mapif->quests_fromsql = mapif_quests_fromsql;
- mapif->quest_delete = mapif_quest_delete;
- mapif->quest_add = mapif_quest_add;
- mapif->quest_update = mapif_quest_update;
mapif->quest_save_ack = mapif_quest_save_ack;
mapif->parse_quest_save = mapif_parse_quest_save;
mapif->send_quests = mapif_send_quests;
mapif->parse_quest_load = mapif_parse_quest_load;
+ /* RoDEX */
+ mapif->parse_rodex_requestinbox = mapif_parse_rodex_requestinbox;
+ mapif->rodex_sendinbox = mapif_rodex_sendinbox;
+ mapif->parse_rodex_checkhasnew = mapif_parse_rodex_checkhasnew;
+ mapif->rodex_sendhasnew = mapif_rodex_sendhasnew;
+ mapif->parse_rodex_updatemail = mapif_parse_rodex_updatemail;
+ mapif->parse_rodex_send = mapif_parse_rodex_send;
+ mapif->rodex_send = mapif_rodex_send;
+ mapif->parse_rodex_checkname = mapif_parse_rodex_checkname;
+ mapif->rodex_checkname = mapif_rodex_checkname;
mapif->load_guild_storage = mapif_load_guild_storage;
mapif->save_guild_storage_ack = mapif_save_guild_storage_ack;
mapif->parse_LoadGuildStorage = mapif_parse_LoadGuildStorage;
mapif->parse_SaveGuildStorage = mapif_parse_SaveGuildStorage;
+ mapif->pAccountStorageLoad = mapif_parse_AccountStorageLoad;
+ mapif->pAccountStorageSave = mapif_parse_AccountStorageSave;
+ mapif->sAccountStorageSaveAck = mapif_send_AccountStorageSaveAck;
+ mapif->account_storage_load = mapif_account_storage_load;
mapif->itembound_ack = mapif_itembound_ack;
- mapif->parse_ItemBoundRetrieve_sub = mapif_parse_ItemBoundRetrieve_sub;
mapif->parse_ItemBoundRetrieve = mapif_parse_ItemBoundRetrieve;
mapif->parse_accinfo = mapif_parse_accinfo;
- mapif->parse_accinfo2 = mapif_parse_accinfo2;
mapif->broadcast = mapif_broadcast;
mapif->wis_message = mapif_wis_message;
mapif->wis_response = mapif_wis_response;
@@ -382,4 +2630,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 ebbddead0..bfdefe4ea 100644
--- a/src/char/mapif.h
+++ b/src/char/mapif.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 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
@@ -40,6 +40,11 @@ struct mapif_interface {
int (*sendallwos) (int sfd, unsigned char *buf, unsigned int len);
int (*send) (int fd, unsigned char *buf, unsigned int len);
void (*send_users_count) (int users);
+ void (*pLoadAchievements) (int fd);
+ void (*sAchievementsToMap) (int fd, int char_id, const struct char_achievements *p);
+ void (*pSaveAchievements) (int fd);
+ void (*achievement_load) (int fd, int char_id);
+ void (*achievement_save) (int char_id, struct char_achievements *p);
void (*auction_message) (int char_id, unsigned char result);
void (*auction_sendlist) (int fd, int char_id, short count, short pages, unsigned char *buf);
void (*parse_auction_requestlist) (int fd);
@@ -51,10 +56,6 @@ struct mapif_interface {
void (*parse_auction_close) (int fd);
void (*auction_bid) (int fd, int char_id, int bid, unsigned char result);
void (*parse_auction_bid) (int fd);
- bool (*elemental_create) (struct s_elemental *ele);
- bool (*elemental_save) (const struct s_elemental *ele);
- bool (*elemental_load) (int ele_id, int char_id, struct s_elemental *ele);
- bool (*elemental_delete) (int ele_id);
void (*elemental_send) (int fd, struct s_elemental *ele, unsigned char flag);
void (*parse_elemental_create) (int fd, const struct s_elemental *ele);
void (*parse_elemental_load) (int fd, int ele_id, int char_id);
@@ -90,7 +91,6 @@ struct mapif_interface {
int (*parse_GuildMemberInfoChange) (int fd, int guild_id, int account_id, int char_id, int type, const char *data, int len);
int (*parse_GuildPosition) (int fd, int guild_id, int idx, const struct guild_position *p);
int (*parse_GuildSkillUp) (int fd, int guild_id, uint16 skill_id, int account_id, int max);
- int (*parse_GuildDeleteAlliance) (struct guild *g, int guild_id, int account_id1, int account_id2, int flag);
int (*parse_GuildAlliance) (int fd, int guild_id1, int guild_id2, int account_id1, int account_id2, int flag);
int (*parse_GuildNotice) (int fd, int guild_id, const char *mes1, const char *mes2);
int (*parse_GuildEmblem) (int fd, int len, int guild_id, int dummy, const char *data);
@@ -102,11 +102,6 @@ struct mapif_interface {
void (*homunculus_loaded) (int fd, int account_id, struct s_homunculus *hd);
void (*homunculus_saved) (int fd, int account_id, bool flag);
void (*homunculus_renamed) (int fd, int account_id, int char_id, unsigned char flag, const char *name);
- bool (*homunculus_create) (struct s_homunculus *hd);
- bool (*homunculus_save) (const struct s_homunculus *hd);
- bool (*homunculus_load) (int homun_id, struct s_homunculus* hd);
- bool (*homunculus_delete) (int homun_id);
- bool (*homunculus_rename) (const char *name);
void (*parse_homunculus_create) (int fd, int len, int account_id, const struct s_homunculus *phd);
void (*parse_homunculus_delete) (int fd, int homun_id);
void (*parse_homunculus_load) (int fd, int account_id, int homun_id);
@@ -116,7 +111,6 @@ struct mapif_interface {
void (*parse_mail_requestinbox) (int fd);
void (*parse_mail_read) (int fd);
void (*mail_sendattach) (int fd, int char_id, struct mail_message *msg);
- void (*mail_getattach) (int fd, int char_id, int mail_id);
void (*parse_mail_getattach) (int fd);
void (*mail_delete) (int fd, int char_id, int mail_id, bool failed);
void (*parse_mail_delete) (int fd);
@@ -125,10 +119,6 @@ struct mapif_interface {
void (*parse_mail_return) (int fd);
void (*mail_send) (int fd, struct mail_message* msg);
void (*parse_mail_send) (int fd);
- bool (*mercenary_create) (struct s_mercenary *merc);
- bool (*mercenary_save) (const struct s_mercenary *merc);
- bool (*mercenary_load) (int merc_id, int char_id, struct s_mercenary *merc);
- bool (*mercenary_delete) (int merc_id);
void (*mercenary_send) (int fd, struct s_mercenary *merc, unsigned char flag);
void (*parse_mercenary_create) (int fd, const struct s_mercenary *merc);
void (*parse_mercenary_load) (int fd, int merc_id, int char_id);
@@ -159,33 +149,36 @@ struct mapif_interface {
int (*pet_noinfo) (int fd, int account_id);
int (*save_pet_ack) (int fd, int account_id, int flag);
int (*delete_pet_ack) (int fd, int flag);
- int (*create_pet) (int fd, int account_id, int char_id, short pet_class, short pet_lv, short pet_egg_id,
- short pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name);
- int (*load_pet) (int fd, int account_id, int char_id, int pet_id);
int (*save_pet) (int fd, int account_id, const struct s_pet *data);
int (*delete_pet) (int fd, int pet_id);
int (*parse_CreatePet) (int fd);
int (*parse_LoadPet) (int fd);
int (*parse_SavePet) (int fd);
int (*parse_DeletePet) (int fd);
- struct quest *(*quests_fromsql) (int char_id, int *count);
- bool (*quest_delete) (int char_id, int quest_id);
- bool (*quest_add) (int char_id, struct quest qd);
- bool (*quest_update) (int char_id, struct quest qd);
void (*quest_save_ack) (int fd, int char_id, bool success);
int (*parse_quest_save) (int fd);
void (*send_quests) (int fd, int char_id, struct quest *tmp_questlog, int num_quests);
int (*parse_quest_load) (int fd);
+ void (*parse_rodex_requestinbox) (int fd);
+ void (*rodex_sendinbox) (int fd, int char_id, int8 opentype, int8 flag, int count, int64 mail_id, struct rodex_maillist *mails);
+ void (*parse_rodex_checkhasnew) (int fd);
+ void (*rodex_sendhasnew) (int fd, int char_id, bool has_new);
+ void (*parse_rodex_updatemail) (int fd);
+ void (*parse_rodex_send) (int fd);
+ void (*rodex_send) (int fd, int sender_id, int receiver_id, int receiver_accountid, bool result);
+ void (*parse_rodex_checkname) (int fd);
+ void (*rodex_checkname) (int fd, int reqchar_id, int target_char_id, short target_class, int target_level, char *name);
int (*load_guild_storage) (int fd, int account_id, int guild_id, char flag);
int (*save_guild_storage_ack) (int fd, int account_id, int guild_id, int fail);
int (*parse_LoadGuildStorage) (int fd);
int (*parse_SaveGuildStorage) (int fd);
+ int (*account_storage_load) (int fd, int account_id);
+ int (*pAccountStorageLoad) (int fd);
+ int (*pAccountStorageSave) (int fd);
+ void (*sAccountStorageSaveAck) (int fd, int account_id, bool save);
int (*itembound_ack) (int fd, int aid, int guild_id);
- int (*parse_ItemBoundRetrieve_sub) (int fd);
void (*parse_ItemBoundRetrieve) (int fd);
void (*parse_accinfo) (int fd);
- void (*parse_accinfo2) (bool success, int map_fd, int u_fd, int u_aid, int account_id, const char *userid, const char *user_pass,
- const char *email, const char *last_ip, const char *lastlogin, const char *pin_code, const char *birthdate, int group_id, int logincount, int state);
int (*broadcast) (const unsigned char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd);
int (*wis_message) (struct WisData *wd);
void (*wis_response) (int fd, const unsigned char *src, int flag);
@@ -200,6 +193,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/packets_hc_struct.h b/src/char/packets_hc_struct.h
new file mode 100644
index 000000000..196493cac
--- /dev/null
+++ b/src/char/packets_hc_struct.h
@@ -0,0 +1,45 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2016-2018 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_PACKETS_HC_STRUCT_H
+#define CHAR_PACKETS_HC_STRUCT_H
+
+#include "common/hercules.h"
+#include "common/mmo.h"
+#include "common/packetsstatic_len.h"
+
+/* Packets Structs */
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#pragma pack(push, 1)
+#endif // not NetBSD < 6 / Solaris
+
+#if PACKETVER_MAIN_NUM >= 20130522 || PACKETVER_RE_NUM >= 20130327 || defined(PACKETVER_ZERO)
+struct PACKET_HC_ACK_CHARINFO_PER_PAGE {
+ int16 packetId;
+ int16 packetLen;
+ // chars list[]
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(HC_ACK_CHARINFO_PER_PAGE, 0x099d);
+#endif
+
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#pragma pack(pop)
+#endif // not NetBSD < 6 / Solaris
+
+#endif // CHAR_PACKETS_HC_STRUCT_H
diff --git a/src/char/pincode.c b/src/char/pincode.c
index fc1a4c037..5a7eb1cab 100644
--- a/src/char/pincode.c
+++ b/src/char/pincode.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -26,6 +26,7 @@
#include "common/cbasetypes.h"
#include "common/conf.h"
#include "common/db.h"
+#include "common/memmgr.h"
#include "common/mmo.h"
#include "common/nullpo.h"
#include "common/random.h"
@@ -36,88 +37,200 @@
#include <stdio.h>
#include <stdlib.h>
-struct pincode_interface pincode_s;
+static struct pincode_interface pincode_s;
struct pincode_interface *pincode;
-void pincode_handle (int fd, struct char_session_data* sd) {
+static void pincode_handle(int fd, struct char_session_data *sd)
+{
struct online_char_data* character;
nullpo_retv(sd);
+
character = (struct online_char_data*)idb_get(chr->online_char_db, sd->account_id);
- if( character && character->pincode_enable > pincode->charselect ){
+
+ if (character && character->pincode_enable > pincode->charselect) {
character->pincode_enable = pincode->charselect * 2;
- }else{
- pincode->sendstate( fd, sd, PINCODE_OK );
+ } else {
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_OK);
return;
}
- if( strlen(sd->pincode) == 4 ){
- if( pincode->changetime && time(NULL) > (sd->pincode_change+pincode->changetime) ){ // User hasn't changed his PIN code for a long time
- pincode->sendstate( fd, sd, PINCODE_EXPIRED );
+ if (strlen(sd->pincode) == 4) {
+ if (pincode->check_blacklist && pincode->isBlacklisted(sd->pincode)) {
+ // Ask player to change pincode to be able to connect
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_EXPIRED);
+ } else if (pincode->changetime && time(NULL) > (sd->pincode_change + pincode->changetime)) {
+ // User hasn't changed his PIN code for a long time
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_EXPIRED);
} else { // Ask user for his PIN code
- pincode->sendstate( fd, sd, PINCODE_ASK );
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_ASK);
}
} else // No PIN code has been set yet
- pincode->sendstate( fd, sd, PINCODE_NOTSET );
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_NOTSET);
- if( character )
+ if (character)
character->pincode_enable = -1;
}
-void pincode_check(int fd, struct char_session_data* sd) {
+static 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 ) ){
+
+ if (pincode->check_blacklist && pincode->isBlacklisted(pin)) {
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_RESTRICT_PW);
+ return;
+ }
+
+ if (pincode->compare(fd, sd, pin)) {
struct online_char_data* character;
- if( (character = (struct online_char_data*)idb_get(chr->online_char_db, sd->account_id)) )
+ if ((character = (struct online_char_data*)idb_get(chr->online_char_db, sd->account_id)))
character->pincode_enable = pincode->charselect * 2;
- pincode->sendstate( fd, sd, PINCODE_OK );
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_OK);
+ } else {
+#if PACKETVER_MAIN_NUM >= 20180124 || PACKETVER_RE_NUM >= 20180124 || PACKETVER_ZERO_NUM >= 20180131
+ pincode->loginstate2(fd, sd, PINCODE_LOGIN_WRONG, PINCODE_LOGIN_FLAG_WRONG);
+#else
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_WRONG);
+#endif
}
}
-int pincode_compare(int fd, struct char_session_data* sd, char* pin) {
+/**
+ * Check if this pincode is blacklisted or not
+ *
+ * @param (const char *) pin The pin to be verified
+ * @return bool
+ */
+static bool pincode_isBlacklisted(const char *pin)
+{
+ int i;
+
+ nullpo_retr(false, pin);
+
+ ARR_FIND(0, VECTOR_LENGTH(pincode->blacklist), i, strcmp(VECTOR_INDEX(pincode->blacklist, i), pin) == 0);
+
+ if (i < VECTOR_LENGTH(pincode->blacklist)) {
+ return true;
+ }
+
+ return false;
+}
+
+static int pincode_compare(int fd, struct char_session_data *sd, char *pin)
+{
nullpo_ret(sd);
nullpo_ret(pin);
- if( strcmp( sd->pincode, pin ) == 0 ){
+
+ if (strcmp(sd->pincode, pin) == 0) {
sd->pincode_try = 0;
return 1;
} else {
- pincode->sendstate( fd, sd, PINCODE_WRONG );
- if( pincode->maxtry && ++sd->pincode_try >= pincode->maxtry ){
- pincode->error( sd->account_id );
+ if (pincode->maxtry && ++sd->pincode_try >= pincode->maxtry) {
+ pincode->error(sd->account_id);
+ chr->authfail_fd(fd, 0);
+ chr->disconnect_player(sd->account_id);
}
return 0;
}
}
-void pincode_change(int fd, struct char_session_data* sd) {
+static 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);
- safestrncpy(oldpin, RFIFOP(fd,6), sizeof(oldpin));
- pincode->decrypt(sd->pincode_seed,oldpin);
- if( !pincode->compare( fd, sd, oldpin ) )
+
+ if (strlen(sd->pincode) != 4)
return;
- safestrncpy(newpin, RFIFOP(fd,10), sizeof(newpin));
- pincode->decrypt(sd->pincode_seed,newpin);
- pincode->update( sd->account_id, newpin );
+ safestrncpy(oldpin, RFIFOP(fd, 6), sizeof(oldpin));
+ pincode->decrypt(sd->pincode_seed, oldpin);
+
+ if (!pincode->compare(fd, sd, oldpin)) {
+ pincode->editstate(fd, sd, PINCODE_EDIT_FAILED);
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_ASK);
+ return;
+ }
+
+ safestrncpy(newpin, RFIFOP(fd, 10), sizeof(newpin));
+ pincode->decrypt(sd->pincode_seed, newpin);
+
+ if (pincode->check_blacklist && pincode->isBlacklisted(newpin)) {
+ pincode->editstate(fd, sd, PINCODE_EDIT_RESTRICT_PW);
+ return;
+ }
+
+ pincode->update(sd->account_id, newpin);
safestrncpy(sd->pincode, newpin, sizeof(sd->pincode));
- pincode->sendstate( fd, sd, PINCODE_ASK );
+ pincode->editstate(fd, sd, PINCODE_EDIT_SUCCESS);
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_ASK);
}
-void pincode_setnew(int fd, struct char_session_data* sd) {
+static void pincode_setnew(int fd, struct char_session_data *sd)
+{
char newpin[5] = "\0\0\0\0";
nullpo_retv(sd);
- safestrncpy(newpin, RFIFOP(fd,6), sizeof(newpin));
- pincode->decrypt(sd->pincode_seed,newpin);
- pincode->update( sd->account_id, newpin );
+
+ if (strlen(sd->pincode) == 4)
+ return;
+
+ safestrncpy(newpin, RFIFOP(fd, 6), sizeof(newpin));
+ pincode->decrypt(sd->pincode_seed, newpin);
+
+ if (pincode->check_blacklist && pincode->isBlacklisted(newpin)) {
+ pincode->makestate(fd, sd, PINCODE_MAKE_RESTRICT_PW);
+ return;
+ }
+
+ pincode->update(sd->account_id, newpin);
safestrncpy(sd->pincode, newpin, sizeof(sd->pincode));
- pincode->sendstate( fd, sd, PINCODE_ASK );
+ pincode->makestate(fd, sd, PINCODE_MAKE_SUCCESS);
+ pincode->loginstate(fd, sd, PINCODE_LOGIN_ASK);
+}
+
+/**
+ * Send state of making new pincode
+ *
+ * @param[in] fd
+ * @param[in, out] sd Session Data
+ * @param[in] state Pincode Edit State
+ */
+static void pincode_makestate(int fd, struct char_session_data *sd, enum pincode_make_response state)
+{
+ nullpo_retv(sd);
+
+ WFIFOHEAD(fd, 8);
+ WFIFOW(fd, 0) = 0x8bb;
+ WFIFOW(fd, 2) = state;
+ WFIFOL(fd, 4) = sd->pincode_seed;
+ WFIFOSET(fd, 8);
+}
+
+/**
+ * Send state of editing pincode
+ *
+ * @param[in] fd
+ * @param[in, out] sd Session Data
+ * @param[in] state Pincode Edit State
+ */
+static void pincode_editstate(int fd, struct char_session_data *sd, enum pincode_edit_response state)
+{
+ nullpo_retv(sd);
+
+ WFIFOHEAD(fd, 8);
+ WFIFOW(fd, 0) = 0x8bf;
+ WFIFOW(fd, 2) = state;
+ WFIFOL(fd, 4) = sd->pincode_seed = rnd() % 0xFFFF;
+ WFIFOSET(fd, 8);
}
// 0 = pin is correct
@@ -129,51 +242,87 @@ void pincode_setnew(int fd, struct char_session_data* sd) {
// 6 = client shows msgstr(1897) Unable to use your KSSN number
// 7 = char select window shows a button - client sends 0x8c5
// 8 = pincode was incorrect
-void pincode_sendstate(int fd, struct char_session_data* sd, uint16 state) {
+static void pincode_loginstate(int fd, struct char_session_data *sd, enum pincode_login_response state)
+{
nullpo_retv(sd);
+
WFIFOHEAD(fd, 12);
WFIFOW(fd, 0) = 0x8b9;
WFIFOL(fd, 2) = sd->pincode_seed = rnd() % 0xFFFF;
WFIFOL(fd, 6) = sd->account_id;
- WFIFOW(fd,10) = state;
- WFIFOSET(fd,12);
+ WFIFOW(fd, 10) = state;
+ WFIFOSET(fd, 12);
}
-void pincode_notifyLoginPinUpdate(int account_id, char* pin) {
+// 0 = pin is correct
+// 1 = ask for pin - client sends 0x8b8
+// 2 = create new pin - client sends 0x8ba
+// 3 = pin must be changed - client 0x8be
+// 4 = create new pin ?? - client sends 0x8ba
+// 5 = client shows msgstr(1896)
+// 6 = client shows msgstr(1897) Unable to use your KSSN number
+// 7 = char select window shows a button - client sends 0x8c5
+// 8 = pincode was incorrect
+// [4144] pincode_loginstate2 can replace pincode_loginstate,
+// but kro using pincode_loginstate2 only for send wrong pin error or locked after 3 pins wrong
+static void pincode_loginstate2(int fd, struct char_session_data *sd, enum pincode_login_response state, enum pincode_login_response2 flag)
+{
+#if PACKETVER_MAIN_NUM >= 20180124 || PACKETVER_RE_NUM >= 20180124 || PACKETVER_ZERO_NUM >= 20180131
+ nullpo_retv(sd);
+
+ WFIFOHEAD(fd, 13);
+ WFIFOW(fd, 0) = 0xae9;
+ WFIFOL(fd, 2) = sd->pincode_seed = rnd() % 0xFFFF;
+ WFIFOL(fd, 6) = sd->account_id;
+ WFIFOW(fd, 10) = state;
+ WFIFOW(fd, 12) = flag;
+ WFIFOSET(fd, 13);
+#endif
+}
+
+static void pincode_notifyLoginPinUpdate(int account_id, char *pin)
+{
nullpo_retv(pin);
+
Assert_retv(chr->login_fd != -1);
- WFIFOHEAD(chr->login_fd,11);
- WFIFOW(chr->login_fd,0) = 0x2738;
- WFIFOL(chr->login_fd,2) = account_id;
- safestrncpy(WFIFOP(chr->login_fd,6), pin, 5);
- WFIFOSET(chr->login_fd,11);
+ WFIFOHEAD(chr->login_fd, 11);
+ WFIFOW(chr->login_fd, 0) = 0x2738;
+ WFIFOL(chr->login_fd, 2) = account_id;
+ safestrncpy(WFIFOP(chr->login_fd, 6), pin, 5);
+ WFIFOSET(chr->login_fd, 11);
}
-void pincode_notifyLoginPinError(int account_id) {
- WFIFOHEAD(chr->login_fd,6);
- WFIFOW(chr->login_fd,0) = 0x2739;
- WFIFOL(chr->login_fd,2) = account_id;
- WFIFOSET(chr->login_fd,6);
+static void pincode_notifyLoginPinError(int account_id)
+{
+ WFIFOHEAD(chr->login_fd, 6);
+ WFIFOW(chr->login_fd, 0) = 0x2739;
+ WFIFOL(chr->login_fd, 2) = account_id;
+ WFIFOSET(chr->login_fd, 6);
}
-void pincode_decrypt(unsigned int userSeed, char* pin) {
+static void pincode_decrypt(unsigned int userSeed, char *pin)
+{
int i;
- char tab[10] = {0,1,2,3,4,5,6,7,8,9};
+ char tab[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
nullpo_retv(pin);
+
for (i = 1; i < 10; i++) {
int pos;
userSeed = pincode->baseSeed + userSeed * pincode->multiplier;
pos = userSeed % (i + 1);
- if( i != pos ){
+ if (i != pos) {
tab[i] ^= tab[pos];
tab[pos] ^= tab[i];
tab[i] ^= tab[pos];
}
}
- 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]);
@@ -188,9 +337,11 @@ void pincode_decrypt(unsigned int userSeed, char* pin) {
*
* @retval false in case of error.
*/
-bool pincode_config_read(const char *filename, const struct config_t *config, bool imported)
+static bool pincode_config_read(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
+ const struct config_setting_t *temp = NULL;
+
nullpo_retr(false, filename);
nullpo_retr(false, config);
@@ -227,28 +378,94 @@ bool pincode_config_read(const char *filename, const struct config_t *config, bo
}
}
+ if (libconfig->setting_lookup_bool_real(setting, "check_blacklisted", &pincode->check_blacklist) == CONFIG_FALSE) {
+ if (!imported) {
+ ShowWarning("pincode 'check_blaclisted' not found, defaulting to false...\n");
+ pincode->check_blacklist = false;
+ }
+ }
+
+ if (pincode->check_blacklist) {
+ if ((temp = libconfig->setting_get_member(setting, "blacklist")) != NULL) {
+ VECTOR_DECL(char *) duplicate;
+ int i, j, size = libconfig->setting_length(temp);
+ VECTOR_INIT(duplicate);
+ VECTOR_ENSURE(duplicate, size, 1);
+ for (i = 0; i < size; i++) {
+ const char *pin = libconfig->setting_get_string_elem(temp, i);
+
+ if (pin == NULL)
+ continue;
+
+ if (strlen(pin) != 4) {
+ ShowError("Wrong size on element %d of blacklist. Desired size = 4, received = %d\n", i, (int)strlen(pin));
+ continue;
+ }
+
+ ARR_FIND(0, VECTOR_LENGTH(duplicate), j, strcmp(VECTOR_INDEX(duplicate, j), pin) == 0);
+
+ if (j < VECTOR_LENGTH(duplicate)) {
+ ShowWarning("Duplicate pin on pincode blacklist. Item #%d\n", i);
+ continue;
+ }
+
+ VECTOR_ENSURE(pincode->blacklist, 1, 1);
+ VECTOR_PUSH(pincode->blacklist, aStrdup(pin));
+ VECTOR_PUSH(duplicate, aStrdup(pin));
+ }
+ while (VECTOR_LENGTH(duplicate) > 0) {
+ aFree(VECTOR_POP(duplicate));
+ }
+ VECTOR_CLEAR(duplicate);
+ } else if (!imported) {
+ ShowError("Pincode Blacklist Check is enabled but there's no blacklist setting! Disabling check.\n");
+ pincode->check_blacklist = false;
+ }
+ }
+
return true;
}
-void pincode_defaults(void) {
+static void do_pincode_init(void)
+{
+ VECTOR_INIT(pincode->blacklist);
+}
+
+static void do_pincode_final(void)
+{
+ while (VECTOR_LENGTH(pincode->blacklist) > 0) {
+ aFree(VECTOR_POP(pincode->blacklist));
+ }
+ VECTOR_CLEAR(pincode->blacklist);
+}
+
+void pincode_defaults(void)
+{
pincode = &pincode_s;
- pincode->enabled = PINCODE_OK;
+ pincode->enabled = 0;
pincode->changetime = 0;
pincode->maxtry = 3;
pincode->charselect = 0;
+ pincode->check_blacklist = false;
pincode->multiplier = 0x3498;
pincode->baseSeed = 0x881234;
+ pincode->init = do_pincode_init;
+ pincode->final = do_pincode_final;
+
pincode->handle = pincode_handle;
pincode->decrypt = pincode_decrypt;
pincode->error = pincode_notifyLoginPinError;
pincode->update = pincode_notifyLoginPinUpdate;
- pincode->sendstate = pincode_sendstate;
+ pincode->makestate = pincode_makestate;
+ pincode->editstate = pincode_editstate;
+ pincode->loginstate = pincode_loginstate;
+ pincode->loginstate2 = pincode_loginstate2;
pincode->setnew = pincode_setnew;
pincode->change = pincode_change;
+ pincode->isBlacklisted = pincode_isBlacklisted;
pincode->compare = pincode_compare;
pincode->check = pincode_check;
pincode->config_read = pincode_config_read;
-
}
diff --git a/src/char/pincode.h b/src/char/pincode.h
index cffaa3054..699758179 100644
--- a/src/char/pincode.h
+++ b/src/char/pincode.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
+ * Copyright (C) 2012-2018 Hercules Dev Team
* Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
@@ -22,18 +22,40 @@
#define CHAR_PINCODE_H
#include "common/hercules.h"
+#include "common/db.h"
/* Forward Declarations */
struct char_session_data;
struct config_t; // common/conf.h
-enum PincodeResponseCode {
- PINCODE_OK = 0,
- PINCODE_ASK = 1,
- PINCODE_NOTSET = 2,
- PINCODE_EXPIRED = 3,
- PINCODE_UNUSED = 7,
- PINCODE_WRONG = 8,
+enum pincode_make_response {
+ PINCODE_MAKE_SUCCESS = 0,
+ PINCODE_MAKE_DUPLICATED = 1,
+ PINCODE_MAKE_RESTRICT_PW = 2,
+ PINCODE_MAKE_PERSONALNUM_PW = 3,
+ PINCODE_MAKE_FAILED = 4,
+};
+
+enum pincode_edit_response {
+ PINCODE_EDIT_SUCCESS = 0x0,
+ PINCODE_EDIT_FAILED = 0x1,
+ PINCODE_EDIT_RESTRICT_PW = 0x2,
+ PINCODE_EDIT_PERSONALNUM_PW = 0x3,
+};
+
+enum pincode_login_response {
+ PINCODE_LOGIN_OK = 0,
+ PINCODE_LOGIN_ASK = 1,
+ PINCODE_LOGIN_NOTSET = 2,
+ PINCODE_LOGIN_EXPIRED = 3,
+ PINCODE_LOGIN_RESTRICT_PW = 5,
+ PINCODE_LOGIN_UNUSED = 7,
+ PINCODE_LOGIN_WRONG = 8,
+};
+
+enum pincode_login_response2 {
+ PINCODE_LOGIN_FLAG_LOCKED = 0,
+ PINCODE_LOGIN_FLAG_WRONG = 2,
};
/**
@@ -45,6 +67,8 @@ struct pincode_interface {
int changetime;
int maxtry;
int charselect;
+ bool check_blacklist;
+ VECTOR_DECL(char *) blacklist;
unsigned int multiplier;
unsigned int baseSeed;
/* handler */
@@ -52,12 +76,18 @@ struct pincode_interface {
void (*decrypt) (unsigned int userSeed, char* pin);
void (*error) (int account_id);
void (*update) (int account_id, char* pin);
- void (*sendstate) (int fd, struct char_session_data* sd, uint16 state);
+ void (*makestate) (int fd, struct char_session_data *sd, enum pincode_make_response state);
+ void (*editstate) (int fd, struct char_session_data *sd, enum pincode_edit_response state);
+ void (*loginstate) (int fd, struct char_session_data *sd, enum pincode_login_response state);
+ void (*loginstate2) (int fd, struct char_session_data *sd, enum pincode_login_response state, enum pincode_login_response2 flag);
void (*setnew) (int fd, struct char_session_data* sd);
void (*change) (int fd, struct char_session_data* sd);
+ bool (*isBlacklisted) (const char *pin);
int (*compare) (int fd, struct char_session_data* sd, char* pin);
void (*check) (int fd, struct char_session_data* sd);
bool (*config_read) (const char *filename, const struct config_t *config, bool imported);
+ void (*init) (void);
+ void (*final) (void);
};
#ifdef HERCULES_CORE