summaryrefslogtreecommitdiff
path: root/src/char/int_clan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/char/int_clan.c')
-rw-r--r--src/char/int_clan.c181
1 files changed, 181 insertions, 0 deletions
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;
+}