summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
authorMurilo Pereti Tavares <murilopereti@gmail.com>2018-01-25 01:15:08 -0200
committerMurilo Pereti Tavares <murilopereti@gmail.com>2018-01-25 01:15:08 -0200
commitfc1684c82d92de81e5688e33a8386cde3c2407db (patch)
treecb6af3fd8e9f940cc4cb9f2181e78c2dc751d203 /src/char
parent33982166de006d777aa2d95a9d95b2778db1c65a (diff)
downloadhercules-fc1684c82d92de81e5688e33a8386cde3c2407db.tar.gz
hercules-fc1684c82d92de81e5688e33a8386cde3c2407db.tar.bz2
hercules-fc1684c82d92de81e5688e33a8386cde3c2407db.tar.xz
hercules-fc1684c82d92de81e5688e33a8386cde3c2407db.zip
Implementation of Official Clan System
All official features work including the autokick for inactive members And the system is completely customizable.
Diffstat (limited to 'src/char')
-rw-r--r--src/char/HPMchar.c1
-rw-r--r--src/char/Makefile.in4
-rw-r--r--src/char/char.c13
-rw-r--r--src/char/int_clan.c181
-rw-r--r--src/char/int_clan.h39
-rw-r--r--src/char/inter.c4
-rw-r--r--src/char/mapif.c6
-rw-r--r--src/char/mapif.h3
8 files changed, 244 insertions, 7 deletions
diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c
index 3a74f443d..43a94604d 100644
--- a/src/char/HPMchar.c
+++ b/src/char/HPMchar.c
@@ -28,6 +28,7 @@
#include "char/geoip.h"
#include "char/inter.h"
#include "char/int_auction.h"
+#include "char/int_clan.h"
#include "char/int_elemental.h"
#include "char/int_guild.h"
#include "char/int_homun.h"
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index 1a7d067a4..fed7ec030 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -40,11 +40,11 @@ MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
-CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_auction.c int_elemental.c int_guild.c \
+CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_auction.c int_clan.c int_elemental.c int_guild.c \
int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \
int_quest.c int_rodex.c int_storage.c pincode.c
CHAR_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(CHAR_C)))
-CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_auction.h int_elemental.h int_guild.h \
+CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_auction.h int_clan.h int_elemental.h int_guild.h \
int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \
int_quest.h int_rodex.h int_storage.h pincode.h
CHAR_PH =
diff --git a/src/char/char.c b/src/char/char.c
index c3fcd9e0a..2532ca154 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -26,6 +26,7 @@
#include "char/HPMchar.h"
#include "char/geoip.h"
#include "char/int_auction.h"
+#include "char/int_clan.h"
#include "char/int_elemental.h"
#include "char/int_guild.h"
#include "char/int_homun.h"
@@ -465,7 +466,8 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->look.head_mid != cp->look.head_mid) || (p->look.head_bottom != cp->look.head_bottom) || (p->delete_date != cp->delete_date) ||
(p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->look.robe != cp->look.robe) ||
(p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font) ||
- (p->uniqueitem_counter != cp->uniqueitem_counter) || (p->hotkey_rowshift != cp->hotkey_rowshift)
+ (p->uniqueitem_counter != cp->uniqueitem_counter) || (p->hotkey_rowshift != cp->hotkey_rowshift) ||
+ (p->clan_id != cp->clan_id) || (p->last_login != cp->last_login)
) {
//Save status
unsigned int opt = 0;
@@ -483,7 +485,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
"`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
"`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u',"
- "`hotkey_rowshift`='%d'"
+ "`hotkey_rowshift`='%d',`clan_id`='%d',`last_login`='%"PRId64"'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
@@ -495,7 +497,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
(unsigned long)p->delete_date, // FIXME: platform-dependent size
p->look.robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
- p->hotkey_rowshift,
+ p->hotkey_rowshift,p->clan_id,p->last_login,
p->account_id, p->char_id) )
{
Sql_ShowDebug(inter->sql_handle);
@@ -1173,7 +1175,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
"`hair_color`,`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`,`slotchange`,"
- "`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`"
+ "`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`,`last_login`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1236,6 +1238,8 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_UINT32, &p->uniqueitem_counter, sizeof p->uniqueitem_counter, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 57, SQLDT_ENUM, &sex, sizeof sex, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 58, SQLDT_UCHAR, &p->hotkey_rowshift, sizeof p->hotkey_rowshift, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 59, SQLDT_INT, &p->clan_id, sizeof p->clan_id, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 60, SQLDT_INT64, &p->last_login, sizeof p->last_login, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
@@ -6424,6 +6428,7 @@ void char_load_defaults(void)
loginif_defaults();
mapif_defaults();
inter_auction_defaults();
+ inter_clan_defaults();
inter_elemental_defaults();
inter_guild_defaults();
inter_homunculus_defaults();
diff --git a/src/char/int_clan.c b/src/char/int_clan.c
new file mode 100644
index 000000000..76a9639c5
--- /dev/null
+++ b/src/char/int_clan.c
@@ -0,0 +1,181 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#define HERCULES_CORE
+
+#include "config/core.h" // DBPATH
+#include "int_clan.h"
+
+#include "char/char.h"
+#include "char/inter.h"
+#include "char/mapif.h"
+#include "common/cbasetypes.h"
+#include "common/memmgr.h"
+#include "common/mmo.h"
+#include "common/nullpo.h"
+#include "common/showmsg.h"
+#include "common/socket.h"
+#include "common/sql.h"
+#include "common/strlib.h"
+#include "common/timer.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+struct inter_clan_interface inter_clan_s;
+struct inter_clan_interface *inter_clan;
+
+/**
+ * Kick offline members of a clan
+ *
+ * Perform the update on the DB to reset clan id to 0
+ * of the members that are inactive for too long
+ *
+ * @param clan_id Id of the clan
+ * @param kick_interval Time needed to consider a player inactive and kick it
+ * @return 0 on failure, 1 on success
+ */
+int inter_clan_kick_inactive_members(int clan_id, int kick_interval)
+{
+ if (clan_id <= 0) {
+ ShowError("inter_clan_kick_inactive_members: Invalid clan id received '%d'\n", clan_id);
+ Assert_retr(0, 0);
+ return 0;
+ } else if (kick_interval <= 0) {
+ ShowError("inter_clan_kick_inactive_members: Invalid kick_interval received '%d'", kick_interval);
+ Assert_retr(0, 0);
+ return 0;
+ }
+
+ // Kick Inactive members
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET "
+ "`clan_id` = 0 WHERE `clan_id` = '%d' AND `online` = 0 AND `last_login` < %"PRId64,
+ char_db, clan_id, (int64)(time(NULL) - kick_interval)))
+ {
+ Sql_ShowDebug(inter->sql_handle);
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * Count members of a clan
+ *
+ * @param clan_id Id of the clan
+ * @param kick_interval Time needed to consider a player inactive and ignore it on the count
+ */
+int inter_clan_count_members(int clan_id, int kick_interval)
+{
+ struct SqlStmt *stmt;
+ int count = 0;
+
+ if (clan_id <= 0) {
+ ShowError("inter_clan_count_members: Invalid clan id received '%d'\n", clan_id);
+ Assert_retr(0, 0);
+ return 0;
+ } else if (kick_interval <= 0) {
+ ShowError("inter_clan_count_member: Invalid kick_interval received '%d'", kick_interval);
+ Assert_retr(0, 0);
+ return 0;
+ }
+
+ stmt = SQL->StmtMalloc(inter->sql_handle);
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return 0;
+ }
+
+ // Count members
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT COUNT(*) FROM `%s` WHERE `clan_id` = ? AND `last_login` >= %"PRId64, char_db, (int64)(time(NULL) - kick_interval))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &clan_id, sizeof(clan_id))
+ || SQL_ERROR == SQL->StmtExecute(stmt)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &count, sizeof(count), NULL, NULL)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return 0;
+ }
+
+ if (SQL->StmtNumRows(stmt) > 0 && SQL_SUCCESS != SQL->StmtNextRow(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return 0;
+ }
+
+ SQL->StmtFree(stmt);
+ return count;
+}
+
+int mapif_parse_ClanMemberCount(int fd, int clan_id, int kick_interval)
+{
+
+ WFIFOHEAD(fd, 10);
+ WFIFOW(fd, 0) = 0x3858;
+ WFIFOL(fd, 2) = clan_id;
+ WFIFOL(fd, 6) = inter_clan->count_members(clan_id, kick_interval);
+ WFIFOSET(fd, 10);
+ return 0;
+}
+
+int mapif_parse_ClanMemberKick(int fd, int clan_id, int kick_interval)
+{
+ int count = 0;
+
+ if (inter_clan->kick_inactive_members(clan_id, kick_interval) == 1)
+ count = inter_clan->count_members(clan_id, kick_interval);
+
+ WFIFOHEAD(fd, 10);
+ WFIFOW(fd, 0) = 0x3858;
+ WFIFOL(fd, 2) = clan_id;
+ WFIFOL(fd, 6) = count;
+ WFIFOSET(fd, 10);
+ return 0;
+}
+
+// Communication from the map server
+// - Can analyzed only one by one packet
+// Data packet length that you set to inter.c
+//- Shouldn't do checking and packet length, RFIFOSKIP is done by the caller
+// Must Return
+// 1 : ok
+// 0 : error
+int inter_clan_parse_frommap(int fd)
+{
+ RFIFOHEAD(fd);
+
+ switch(RFIFOW(fd, 0)) {
+ case 0x3044: mapif->parse_ClanMemberCount(fd, RFIFOL(fd, 2), RFIFOL(fd, 6)); break;
+ case 0x3045: mapif->parse_ClanMemberKick(fd, RFIFOL(fd, 2), RFIFOL(fd, 6)); break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void inter_clan_defaults(void)
+{
+ inter_clan = &inter_clan_s;
+
+ inter_clan->kick_inactive_members = inter_clan_kick_inactive_members;
+ inter_clan->count_members = inter_clan_count_members;
+ inter_clan->parse_frommap = inter_clan_parse_frommap;
+}
diff --git a/src/char/int_clan.h b/src/char/int_clan.h
new file mode 100644
index 000000000..e7b44ecd3
--- /dev/null
+++ b/src/char/int_clan.h
@@ -0,0 +1,39 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef CHAR_INT_CLAN_H
+#define CHAR_INT_CLAN_H
+
+#include "common/mmo.h"
+
+/**
+ * inter clan Interface
+ **/
+struct inter_clan_interface {
+ int (*kick_inactive_members) (int clan_id, int kick_interval);
+ int (*count_members) (int clan_id, int kick_interval);
+ int (*parse_frommap) (int fd);
+};
+
+#ifdef HERCULES_CORE
+void inter_clan_defaults(void);
+#endif // HERCULES_CORE
+
+HPShared struct inter_clan_interface *inter_clan;
+#endif /* CHAR_INT_CLAN_H */
diff --git a/src/char/inter.c b/src/char/inter.c
index 557ee5313..baa000d82 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -25,6 +25,7 @@
#include "char/char.h"
#include "char/geoip.h"
#include "char/int_auction.h"
+#include "char/int_clan.h"
#include "char/int_elemental.h"
#include "char/int_guild.h"
#include "char/int_homun.h"
@@ -72,7 +73,7 @@ int inter_recv_packet_length[] = {
6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010- Account Storage [Smokexyz]
-1,10,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, // 3020- Party
-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030-
- -1, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040-
+ -1, 9, 0, 0, 10,10, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040- Clan System(3044-3045)
-1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus], Item Bound [Mhalicot]
6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish]
-1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil]
@@ -1420,6 +1421,7 @@ int inter_parse_frommap(int fd)
|| inter_auction->parse_frommap(fd)
|| inter_quest->parse_frommap(fd)
|| inter_rodex->parse_frommap(fd)
+ || inter_clan->parse_frommap(fd)
)
break;
else
diff --git a/src/char/mapif.c b/src/char/mapif.c
index 9fccd691b..241edc925 100644
--- a/src/char/mapif.c
+++ b/src/char/mapif.c
@@ -221,6 +221,9 @@ int mapif_parse_Registry(int fd);
int mapif_parse_RegistryRequest(int fd);
void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, const char *const name);
int mapif_parse_NameChangeRequest(int fd);
+// Clan System
+int mapif_parse_ClanMemberKick(int fd, int clan_id, int kick_interval);
+int mapif_parse_ClanMemberCount(int fd, int clan_id, int kick_interval);
struct mapif_interface mapif_s;
struct mapif_interface *mapif;
@@ -411,4 +414,7 @@ void mapif_defaults(void) {
mapif->parse_RegistryRequest = mapif_parse_RegistryRequest;
mapif->namechange_ack = mapif_namechange_ack;
mapif->parse_NameChangeRequest = mapif_parse_NameChangeRequest;
+ /* Clan System */
+ mapif->parse_ClanMemberKick = mapif_parse_ClanMemberKick;
+ mapif->parse_ClanMemberCount = mapif_parse_ClanMemberCount;
}
diff --git a/src/char/mapif.h b/src/char/mapif.h
index a78940ba2..f03f1ad9a 100644
--- a/src/char/mapif.h
+++ b/src/char/mapif.h
@@ -213,6 +213,9 @@ struct mapif_interface {
int (*parse_RegistryRequest) (int fd);
void (*namechange_ack) (int fd, int account_id, int char_id, int type, int flag, const char *name);
int (*parse_NameChangeRequest) (int fd);
+ // Clan System
+ int (*parse_ClanMemberKick) (int fd, int clan_id, int kick_interval);
+ int (*parse_ClanMemberCount) (int fd, int clan_id, int kick_interval);
};
#ifdef HERCULES_CORE