summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/Makefile.in8
-rw-r--r--src/map/atcommand.c278
-rw-r--r--src/map/channel.c833
-rw-r--r--src/map/channel.h119
-rw-r--r--src/map/clif.c613
-rw-r--r--src/map/clif.h67
-rw-r--r--src/map/guild.c60
-rw-r--r--src/map/instance.c3
-rw-r--r--src/map/irc-bot.c54
-rw-r--r--src/map/irc-bot.h6
-rw-r--r--src/map/map.c21
-rw-r--r--src/map/map.h4
-rw-r--r--src/map/pc.c5
-rw-r--r--src/map/pc.h5
-rw-r--r--src/map/script.c26
15 files changed, 1203 insertions, 899 deletions
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index ee8b7ac56..90bb55694 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -22,15 +22,15 @@ MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
MT19937AR_INCLUDE = -I$(MT19937AR_D)
-MAP_C = atcommand.c battle.c battleground.c buyingstore.c chat.c chrif.c \
- clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \
+MAP_C = atcommand.c battle.c battleground.c buyingstore.c channel.c chat.c \
+ chrif.c clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \
instance.c intif.c irc-bot.c itemdb.c log.c mail.c map.c mapreg_sql.c \
mercenary.c mob.c npc.c npc_chat.c party.c path.c pc.c pc_groups.c \
pet.c quest.c script.c searchstore.c skill.c status.c storage.c \
trade.c unit.c vending.c
MAP_OBJ = $(addprefix obj_sql/, $(patsubst %c,%o,$(MAP_C)))
-MAP_H = atcommand.h battle.h battleground.h buyingstore.h chat.h chrif.h \
- clif.h date.h duel.h elemental.h guild.h homunculus.h HPMmap.h \
+MAP_H = atcommand.h battle.h battleground.h buyingstore.h channel.h chat.h \
+ chrif.h clif.h date.h duel.h elemental.h guild.h homunculus.h HPMmap.h \
instance.h intif.h irc-bot.h itemdb.h log.h mail.h map.h mapreg.h \
mercenary.h mob.h npc.h packets.h packets_struct.h party.h path.h \
pc.h pc_groups.h pet.h quest.h script.h searchstore.h skill.h \
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index d75282746..a6e4d7265 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -14,6 +14,7 @@
#include "HPMmap.h"
#include "battle.h"
+#include "channel.h"
#include "chat.h"
#include "chrif.h"
#include "clif.h"
@@ -5461,7 +5462,7 @@ ACMD(autotrade)
((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, SCFLAG_NONE);
}
- clif->chsys_quit(sd);
+ channel->quit(sd);
clif->authfail_fd(sd->fd, 15);
@@ -8611,76 +8612,45 @@ ACMD(cart) {
#undef MC_CART_MDFY
}
/* [Ind/Hercules] */
-ACMD(join) {
- struct hChSysCh *channel = NULL;
- char name[HCHSYS_NAME_LENGTH], pass[HCHSYS_NAME_LENGTH];
+ACMD(join)
+{
+ struct channel_data *chan = NULL;
+ char name[HCS_NAME_LENGTH], pass[HCS_NAME_LENGTH];
+ enum channel_operation_status ret = HCS_STATUS_OK;
if (!message || !*message || sscanf(message, "%19s %19s", name, pass) < 1) {
sprintf(atcmd_output, msg_txt(1399),command); // Unknown Channel (usage: %s <#channel_name>)
clif->message(fd, atcmd_output);
return false;
}
- if (clif->hChSys->local && strcmpi(name + 1, clif->hChSys->local_name) == 0) {
- if( !map->list[sd->bl.m].channel ) {
- clif->chsys_mjoin(sd);
- if( map->list[sd->bl.m].channel ) /* join might have refused, map has chatting capabilities disabled */
- return true;
- } else
- channel = map->list[sd->bl.m].channel;
- } else if (clif->hChSys->ally && sd->status.guild_id && strcmpi(name + 1, clif->hChSys->ally_name) == 0) {
- struct guild *g = sd->guild;
- if( !g ) return false;/* unlikely, but we wont let it crash anyway. */
- channel = g->channel;
- } else if( !( channel = strdb_get(clif->channel_db, name + 1) ) ) {
- sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>)
- clif->message(fd, atcmd_output);
- return false;
- }
- if( !channel ) {
+ chan = channel->search(name, sd);
+
+ if(!chan) {
sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>)
clif->message(fd, atcmd_output);
return false;
}
- if( idb_exists(channel->users, sd->status.char_id) ) {
+ ret = channel->join(chan, sd, pass, false);
+
+ if (ret == HCS_STATUS_ALREADY) {
sprintf(atcmd_output, msg_txt(1436),name); // You're already in the '%s' channel
clif->message(fd, atcmd_output);
return false;
}
- if( channel->pass[0] != '\0' && strcmp(channel->pass,pass) != 0 ) {
- if( pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
- sd->stealth = true;
- } else {
- sprintf(atcmd_output, msg_txt(1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> <password>)
- clif->message(fd, atcmd_output);
- return false;
- }
- }
- if( channel->banned && idb_exists(channel->banned, sd->status.account_id) ) {
- sprintf(atcmd_output, msg_txt(1438),name); // You cannot join the '%s' channel because you've been banned from it
+ if (ret == HCS_STATUS_NOPERM) {
+ sprintf(atcmd_output, msg_txt(1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> <password>)
clif->message(fd, atcmd_output);
return false;
}
- if (!(channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) {
- sprintf(atcmd_output, msg_txt(1403),name); // You're now in the '%s' channel
+ if (ret == HCS_STATUS_BANNED) {
+ sprintf(atcmd_output, msg_txt(1438),name); // You cannot join the '%s' channel because you've been banned from it
clif->message(fd, atcmd_output);
+ return false;
}
- if( channel->type == hChSys_ALLY ) {
- struct guild *g = sd->guild;
- int i;
- for (i = 0; i < MAX_GUILDALLIANCE; i++) {
- struct guild *sg = NULL;
- if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) {
- if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) {
- clif->chsys_join(sg->channel,sd);
- }
- }
- }
- }
- clif->chsys_join(channel,sd);
return true;
}
@@ -8736,81 +8706,75 @@ static inline void atcmd_channel_help(int fd, const char *command, bool can_crea
}
/* [Ind/Hercules] */
ACMD(channel) {
- struct hChSysCh *channel;
- char subcmd[HCHSYS_NAME_LENGTH], sub1[HCHSYS_NAME_LENGTH], sub2[HCHSYS_NAME_LENGTH], sub3[HCHSYS_NAME_LENGTH];
+ struct channel_data *chan;
+ char subcmd[HCS_NAME_LENGTH], sub1[HCS_NAME_LENGTH], sub2[HCS_NAME_LENGTH], sub3[HCS_NAME_LENGTH];
unsigned char k = 0;
sub1[0] = sub2[0] = sub3[0] = '\0';
if (!message || !*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) {
- atcmd_channel_help(fd,command, (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)));
+ atcmd_channel_help(fd,command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)));
return true;
}
- if (strcmpi(subcmd,"create") == 0 && (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) {
+ if (strcmpi(subcmd,"create") == 0 && (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) {
// sub1 = channel name; sub2 = password; sub3 = unused
size_t len = strlen(sub1);
+ const char *pass = *sub2 ? sub2 : NULL;
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
- } else if (len < 3 || len > HCHSYS_NAME_LENGTH) {
- sprintf(atcmd_output, msg_txt(1406), HCHSYS_NAME_LENGTH);// Channel length must be between 3 and %d
+ } else if (len < 3 || len > HCS_NAME_LENGTH) {
+ sprintf(atcmd_output, msg_txt(1406), HCS_NAME_LENGTH);// Channel length must be between 3 and %d
clif->message(fd, atcmd_output);
return false;
} else if (sub3[0] != '\0') {
clif->message(fd, msg_txt(1408)); // Channel password may not contain spaces
return false;
}
- if (strcmpi(sub1 + 1, clif->hChSys->local_name) == 0 || strcmpi(sub1 + 1, clif->hChSys->ally_name) == 0 || strdb_exists(clif->channel_db, sub1 + 1)) {
+ if (strcmpi(sub1 + 1, channel->config->local_name) == 0 || strcmpi(sub1 + 1, channel->config->ally_name) == 0 || strdb_exists(channel->db, sub1 + 1)) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- CREATE( channel, struct hChSysCh, 1 );
- clif->chsys_create(channel,sub1 + 1,sub2,0);
-
- channel->owner = sd->status.char_id;
- channel->type = hChSys_PRIVATE;
-
- if( !( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) {
- sprintf(atcmd_output, msg_txt(1403),sub1); // You're now in the '%s' channel
- clif->message(fd, atcmd_output);
- }
+ chan = channel->create(HCS_TYPE_PRIVATE, sub1 + 1, 0);
+ channel->set_password(chan, pass);
+ chan->owner = sd->status.char_id;
- clif->chsys_join(channel,sd);
+ channel->join(chan, sd, pass, false);
} else if (strcmpi(subcmd,"list") == 0) {
// sub1 = list type; sub2 = unused; sub3 = unused
if (sub1[0] != '\0' && strcmpi(sub1,"colors") == 0) {
char mout[40];
- for (k = 0; k < clif->hChSys->colors_count; k++) {
+ for (k = 0; k < channel->config->colors_count; k++) {
unsigned short msg_len = 1;
- msg_len += sprintf(mout, "[ %s list colors ] : %s", command, clif->hChSys->colors_name[k]);
+ msg_len += sprintf(mout, "[ %s list colors ] : %s", command, channel->config->colors_name[k]);
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = msg_len + 12;
WFIFOL(fd,4) = 0;
- WFIFOL(fd,8) = clif->hChSys->colors[k];
+ WFIFOL(fd,8) = channel->config->colors[k];
safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
WFIFOSET(fd, msg_len + 12);
}
} else {
- DBIterator *iter = db_iterator(clif->channel_db);
+ DBIterator *iter = db_iterator(channel->db);
bool show_all = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ? true : false;
clif->message(fd, msg_txt(1410)); // -- Public Channels
- if (clif->hChSys->local) {
- sprintf(atcmd_output, msg_txt(1409), clif->hChSys->local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
+ if (channel->config->local) {
+ sprintf(atcmd_output, msg_txt(1409), channel->config->local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
- if (clif->hChSys->ally && sd->status.guild_id) {
+ if (channel->config->ally && sd->status.guild_id) {
struct guild *g = sd->guild;
if( !g ) { dbi_destroy(iter); return false; }
- sprintf(atcmd_output, msg_txt(1409), clif->hChSys->ally_name, db_size(g->channel->users));// - #%s ( %d users )
+ sprintf(atcmd_output, msg_txt(1409), channel->config->ally_name, db_size(g->channel->users));// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
- for (channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) {
- if (show_all || channel->type == hChSys_PUBLIC || channel->type == hChSys_IRC) {
- sprintf(atcmd_output, msg_txt(1409), channel->name, db_size(channel->users));// - #%s ( %d users )
+ for (chan = dbi_first(iter); dbi_exists(iter); chan = dbi_next(iter)) {
+ if (show_all || chan->type == HCS_TYPE_PUBLIC || chan->type == HCS_TYPE_IRC) {
+ sprintf(atcmd_output, msg_txt(1409), chan->name, db_size(chan->users));// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
}
@@ -8823,29 +8787,29 @@ ACMD(channel) {
return false;
}
- if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
+ if (!(chan = channel->search(sub1, sd))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
+ if (chan->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- for (k = 0; k < clif->hChSys->colors_count; k++) {
- if (strcmpi(sub2, clif->hChSys->colors_name[k]) == 0)
+ for (k = 0; k < channel->config->colors_count; k++) {
+ if (strcmpi(sub2, channel->config->colors_name[k]) == 0)
break;
}
- if (k == clif->hChSys->colors_count) {
+ if (k == channel->config->colors_count) {
sprintf(atcmd_output, msg_txt(1411), sub2);// Unknown color '%s'
clif->message(fd, atcmd_output);
return false;
}
- channel->color = k;
- sprintf(atcmd_output, msg_txt(1413), sub1, clif->hChSys->colors_name[k]);// '%s' channel color updated to '%s'
+ chan->color = k;
+ sprintf(atcmd_output, msg_txt(1413), sub1, channel->config->colors_name[k]);// '%s' channel color updated to '%s'
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"leave") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
@@ -8862,17 +8826,17 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
return false;
}
- if (sd->channels[k]->type == hChSys_ALLY) {
+ if (sd->channels[k]->type == HCS_TYPE_ALLY) {
do {
for (k = 0; k < sd->channel_count; k++) {
- if (sd->channels[k]->type == hChSys_ALLY) {
- clif->chsys_left(sd->channels[k],sd);
+ if (sd->channels[k]->type == HCS_TYPE_ALLY) {
+ channel->leave(sd->channels[k],sd);
break;
}
}
} while (k != sd->channel_count);
} else {
- clif->chsys_left(sd->channels[k],sd);
+ channel->leave(sd->channels[k],sd);
}
sprintf(atcmd_output, msg_txt(1426),sub1); // You've left the '%s' channel
clif->message(fd, atcmd_output);
@@ -8910,26 +8874,20 @@ ACMD(channel) {
} else if (strcmpi(subcmd,"ban") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
struct map_session_data *pl_sd = NULL;
- struct hChSysBanEntry *entry = NULL;
char sub4[NAME_LENGTH]; ///< player name
+ enum channel_operation_status ret = HCS_STATUS_OK;
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
+ if (!(chan = channel->search(sub1, sd))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
- sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
- clif->message(fd, atcmd_output);
- return false;
- }
-
if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) {
sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
@@ -8942,25 +8900,24 @@ ACMD(channel) {
return false;
}
- if (pc_has_permission(pl_sd, PC_PERM_HCHSYS_ADMIN)) {
- clif->message(fd, msg_txt(1464)); // Ban failed, not possible to ban this user.
+ ret = channel->ban(chan, sd, pl_sd);
+
+ if (ret == HCS_STATUS_NOPERM) {
+ sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
+ clif->message(fd, atcmd_output);
return false;
}
- if (channel->banned && idb_exists(channel->banned,pl_sd->status.account_id)) {
+ if (ret == HCS_STATUS_ALREADY) {
sprintf(atcmd_output, msg_txt(1465), pl_sd->status.name);// Player '%s' is already banned from this channel
clif->message(fd, atcmd_output);
return false;
}
- if (!channel->banned)
- channel->banned = idb_alloc(DB_OPT_BASE|DB_OPT_ALLOW_NULL_DATA|DB_OPT_RELEASE_DATA);
-
- CREATE(entry, struct hChSysBanEntry, 1);
- safestrncpy(entry->name, pl_sd->status.name, NAME_LENGTH);
- idb_put(channel->banned, pl_sd->status.account_id, entry);
-
- clif->chsys_left(channel,pl_sd);
+ if (ret != HCS_STATUS_OK/*ret == HCS_STATUS_FAIL*/) {
+ clif->message(fd, msg_txt(1464)); // Ban failed, not possible to ban this user.
+ return false;
+ }
sprintf(atcmd_output, msg_txt(1437),pl_sd->status.name,sub1); // Player '%s' has now been banned from '%s' channel
clif->message(fd, atcmd_output);
@@ -8968,74 +8925,65 @@ ACMD(channel) {
// sub1 = channel name; sub2 = unused; sub3 = unused
struct map_session_data *pl_sd = NULL;
char sub4[NAME_LENGTH]; ///< player name
+ enum channel_operation_status ret = HCS_STATUS_OK;
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
+ if (!(chan = channel->search(sub1, sd))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
- sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
- clif->message(fd, atcmd_output);
- return false;
- }
- if (!channel->banned) {
- sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
+ if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) {
+ sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
return false;
}
- if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) {
+ if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) {
sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
return false;
}
- if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) {
- sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
+ ret = channel->unban(chan, sd, pl_sd);
+ if (ret == HCS_STATUS_NOPERM) {
+ sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if (!idb_exists(channel->banned,pl_sd->status.account_id)) {
+ if (ret == HCS_STATUS_ALREADY) {
sprintf(atcmd_output, msg_txt(1440), pl_sd->status.name);// Player '%s' is not banned from this channel
clif->message(fd, atcmd_output);
return false;
}
- idb_remove(channel->banned, pl_sd->status.account_id);
- if (!db_size(channel->banned)) {
- db_destroy(channel->banned);
- channel->banned = NULL;
- }
-
sprintf(atcmd_output, msg_txt(1441),pl_sd->status.name,sub1); // Player '%s' has now been unbanned from the '%s' channel
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"unbanall") == 0) {
+ enum channel_operation_status ret = HCS_STATUS_OK;
// sub1 = channel name; sub2 = unused; sub3 = unused
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
+ if (!(chan = channel->search(sub1, sd))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
+ ret = channel->unban(chan, sd, NULL);
+ if (ret == HCS_STATUS_NOPERM) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if (!channel->banned) {
+ if (ret == HCS_STATUS_ALREADY) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
return false;
}
- db_destroy(channel->banned);
- channel->banned = NULL;
sprintf(atcmd_output, msg_txt(1442),sub1); // Removed all bans from '%s' channel
clif->message(fd, atcmd_output);
@@ -9049,27 +8997,27 @@ ACMD(channel) {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
+ if (!(chan = channel->search(sub1, sd))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if (channel->owner != sd->status.char_id && !isA) {
+ if (chan->owner != sd->status.char_id && !isA) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if (!channel->banned) {
+ if (!chan->banned) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
return false;
}
- sprintf(atcmd_output, msg_txt(1443), channel->name);// -- '%s' ban list
+ sprintf(atcmd_output, msg_txt(1443), chan->name);// -- '%s' ban list
clif->message(fd, atcmd_output);
- iter = db_iterator(channel->banned);
+ iter = db_iterator(chan->banned);
for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) {
- struct hChSysBanEntry * entry = DB->data2ptr(data);
+ struct channel_ban_entry *entry = DB->data2ptr(data);
if (!isA)
sprintf(atcmd_output, msg_txt(1444), entry->name);// - %s %s
@@ -9090,12 +9038,12 @@ ACMD(channel) {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
+ if (!(chan = channel->search(sub1, sd))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
+ if (chan->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
@@ -9119,60 +9067,60 @@ ACMD(channel) {
return false;
}
if (sub3[0] == '\0') {
- if (k == hChSys_OPT_MSG_DELAY) {
+ if (k == HCS_OPT_MSG_DELAY) {
sprintf(atcmd_output, msg_txt(1466), opt_str[k]);// For '%s' you need the amount of seconds (from 0 to 10)
clif->message(fd, atcmd_output);
return false;
- } else if (channel->opt & k) {
+ } else if (chan->options & k) {
sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel setopt %s 0'
clif->message(fd, atcmd_output);
return false;
} else {
- channel->opt |= k;
- sprintf(atcmd_output, msg_txt(1450), opt_str[k],channel->name);//option '%s' is now enabled for channel '%s'
+ channel->set_options(chan, chan->options | k);
+ sprintf(atcmd_output, msg_txt(1450), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s'
clif->message(fd, atcmd_output);
return true;
}
} else {
int v = atoi(sub3);
- if (k == hChSys_OPT_MSG_DELAY) {
+ if (k == HCS_OPT_MSG_DELAY) {
if (v < 0 || v > 10) {
sprintf(atcmd_output, msg_txt(1451), v, opt_str[k]);// value '%d' for option '%s' is out of range (limit is 0-10)
clif->message(fd, atcmd_output);
return false;
}
if (v == 0) {
- channel->opt &=~ k;
- channel->msg_delay = 0;
- sprintf(atcmd_output, msg_txt(1453), opt_str[k],channel->name,v);// option '%s' is now disabled for channel '%s'
+ channel->set_options(chan, chan->options&~k);
+ chan->msg_delay = 0;
+ sprintf(atcmd_output, msg_txt(1453), opt_str[k],chan->name,v);// option '%s' is now disabled for channel '%s'
clif->message(fd, atcmd_output);
return true;
} else {
- channel->opt |= k;
- channel->msg_delay = v;
- sprintf(atcmd_output, msg_txt(1452), opt_str[k],channel->name,v);// option '%s' is now enabled for channel '%s' with %d seconds
+ channel->set_options(chan, chan->options | k);
+ chan->msg_delay = v;
+ sprintf(atcmd_output, msg_txt(1452), opt_str[k],chan->name,v);// option '%s' is now enabled for channel '%s' with %d seconds
clif->message(fd, atcmd_output);
return true;
}
} else {
if (v) {
- if (channel->opt & k) {
+ if (chan->options & k) {
sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel opt %s 0'
clif->message(fd, atcmd_output);
return false;
} else {
- channel->opt |= k;
- sprintf(atcmd_output, msg_txt(1454), opt_str[k],channel->name);//option '%s' is now enabled for channel '%s'
+ channel->set_options(chan, chan->options | k);
+ sprintf(atcmd_output, msg_txt(1454), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s'
clif->message(fd, atcmd_output);
}
} else {
- if (!(channel->opt & k)) {
- sprintf(atcmd_output, msg_txt(1454), opt_str[k],channel->name); // option '%s' is not enabled on channel '%s'
+ if (!(chan->options & k)) {
+ sprintf(atcmd_output, msg_txt(1454), opt_str[k],chan->name); // option '%s' is not enabled on channel '%s'
clif->message(fd, atcmd_output);
return false;
} else {
- channel->opt &=~ k;
- sprintf(atcmd_output, msg_txt(1453), opt_str[k],channel->name);// option '%s' is now disabled for channel '%s'
+ channel->set_options(chan, chan->options&~k);
+ sprintf(atcmd_output, msg_txt(1453), opt_str[k],chan->name);// option '%s' is now disabled for channel '%s'
clif->message(fd, atcmd_output);
return true;
}
@@ -9180,7 +9128,7 @@ ACMD(channel) {
}
}
} else {
- atcmd_channel_help(fd, command, (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)));
+ atcmd_channel_help(fd, command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)));
}
return true;
}
@@ -9191,14 +9139,14 @@ ACMD(fontcolor) {
char mout[40];
if( !message || !*message ) {
- for( k = 0; k < clif->hChSys->colors_count; k++ ) {
- msg_len += sprintf(mout, "[ %s ] : %s", command, clif->hChSys->colors_name[k]);
+ for( k = 0; k < channel->config->colors_count; k++ ) {
+ msg_len += sprintf(mout, "[ %s ] : %s", command, channel->config->colors_name[k]);
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = msg_len + 12;
WFIFOL(fd,4) = 0;
- WFIFOL(fd,8) = clif->hChSys->colors[k];
+ WFIFOL(fd,8) = channel->config->colors[k];
safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
WFIFOSET(fd, msg_len + 12);
}
@@ -9210,24 +9158,24 @@ ACMD(fontcolor) {
return true;
}
- for( k = 0; k < clif->hChSys->colors_count; k++ ) {
- if (strcmpi(message, clif->hChSys->colors_name[k]) == 0)
+ for( k = 0; k < channel->config->colors_count; k++ ) {
+ if (strcmpi(message, channel->config->colors_name[k]) == 0)
break;
}
- if( k == clif->hChSys->colors_count ) {
+ if( k == channel->config->colors_count ) {
sprintf(atcmd_output, msg_txt(1411), message);// Unknown color '%s'
clif->message(fd, atcmd_output);
return false;
}
sd->fontcolor = k + 1;
- msg_len += sprintf(mout, "Color changed to '%s'", clif->hChSys->colors_name[k]);
+ msg_len += sprintf(mout, "Color changed to '%s'", channel->config->colors_name[k]);
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = msg_len + 12;
WFIFOL(fd,4) = 0;
- WFIFOL(fd,8) = clif->hChSys->colors[k];
+ WFIFOL(fd,8) = channel->config->colors[k];
safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
WFIFOSET(fd, msg_len + 12);
return true;
diff --git a/src/map/channel.c b/src/map/channel.c
new file mode 100644
index 000000000..34ce60211
--- /dev/null
+++ b/src/map/channel.c
@@ -0,0 +1,833 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#define HERCULES_CORE
+
+#include "channel.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "atcommand.h"
+#include "guild.h"
+#include "instance.h"
+#include "irc-bot.h"
+#include "map.h"
+#include "pc.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
+
+struct channel_interface channel_s;
+
+static struct Channel_Config channel_config;
+
+/**
+ * Returns the named channel.
+ *
+ * @param name The channel name
+ * @param sd The issuer character, for character-specific channels (i.e. map, ally)
+ * @return a pointer to the channel, or NULL.
+ */
+struct channel_data *channel_search(const char *name, struct map_session_data *sd)
+{
+ const char *realname = name;
+ if (!realname || !*realname)
+ return NULL;
+ if (*realname == '#') {
+ realname++;
+ if (!*realname)
+ return NULL;
+ }
+
+ if (channel->config->local && strcmpi(realname, channel->config->local_name) == 0) {
+ if (!sd)
+ return NULL;
+ if (!map->list[sd->bl.m].channel) {
+ channel->map_join(sd);
+ }
+ return map->list[sd->bl.m].channel;
+ }
+
+ if (channel->config->ally && strcmpi(realname, channel->config->ally_name) == 0) {
+ if (!sd || !sd->status.guild_id || !sd->guild)
+ return NULL;
+ return sd->guild->channel;
+ }
+
+ return strdb_get(channel->db, realname);
+}
+
+/**
+ * Creates a chat channel.
+ *
+ * If the channel type isn't HCS_TYPE_MAP or HCS_TYPE_ALLY, the channel is added to the channel->db.
+ *
+ * @param type The channel type.
+ * @param name The channel name.
+ * @param color The channel chat color.
+ * @return A pointer to the created channel.
+ */
+struct channel_data *channel_create(enum channel_types type, const char *name, unsigned char color)
+{
+ struct channel_data *chan;
+
+ if (!name)
+ return NULL;
+
+ CREATE(chan, struct channel_data, 1);
+ chan->users = idb_alloc(DB_OPT_BASE);
+ safestrncpy(chan->name, name, HCS_NAME_LENGTH);
+ chan->color = color;
+
+ chan->options = HCS_OPT_BASE;
+ chan->banned = NULL;
+
+ chan->msg_delay = 0;
+
+ chan->type = type;
+ if (chan->type != HCS_TYPE_MAP && chan->type != HCS_TYPE_ALLY)
+ strdb_put(channel->db, chan->name, chan);
+ return chan;
+}
+
+/**
+ * Deletes a chat channel.
+ *
+ * @param chan The channel to delete
+ */
+void channel_delete(struct channel_data *chan)
+{
+ nullpo_retv(chan);
+
+ if (db_size(chan->users) && !channel->config->closing) {
+ DBIterator *iter;
+ struct map_session_data *sd;
+ iter = db_iterator(chan->users);
+ for (sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter)) {
+ channel->leave_sub(chan, sd);
+ }
+ dbi_destroy(iter);
+ }
+ if (chan->banned) {
+ db_destroy(chan->banned);
+ chan->banned = NULL;
+ }
+ db_destroy(chan->users);
+ if (chan->m) {
+ map->list[chan->m].channel = NULL;
+ aFree(chan);
+ } else if (chan->type == HCS_TYPE_ALLY) {
+ aFree(chan);
+ } else if (!channel->config->closing) {
+ strdb_remove(channel->db, chan->name);
+ }
+}
+
+/**
+ * Sets a chat channel password.
+ *
+ * @param chan The channel to edit.
+ * @param pass The password to set. Pass NULL to remove existing passwords.
+ */
+void channel_set_password(struct channel_data *chan, const char *password)
+{
+ nullpo_retv(chan);
+ if (password)
+ safestrncpy(chan->password, password, HCS_NAME_LENGTH);
+ else
+ chan->password[0] = '\0';
+}
+
+/**
+ * Bans a character from the given channel.
+ *
+ * @param chan The channel.
+ * @param ssd The source character, if any.
+ * @param tsd The target character.
+ * @retval HCS_STATUS_OK if the operation succeeded.
+ * @retval HCS_STATUS_ALREADY if the target character is already banned.
+ * @retval HCS_STATUS_NOPERM if the source character doesn't have enough permissions.
+ * @retval HCS_STATUS_FAIL in case of generic failure.
+ */
+enum channel_operation_status channel_ban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd)
+{
+ struct channel_ban_entry *entry = NULL;
+
+ nullpo_retr(HCS_STATUS_FAIL, chan);
+ nullpo_retr(HCS_STATUS_FAIL, tsd);
+
+ if (ssd && chan->owner != ssd->status.char_id && !pc_has_permission(ssd, PC_PERM_HCHSYS_ADMIN))
+ return HCS_STATUS_NOPERM;
+
+ if (pc_has_permission(tsd, PC_PERM_HCHSYS_ADMIN))
+ return HCS_STATUS_FAIL;
+
+ if (chan->banned && idb_exists(chan->banned, tsd->status.account_id))
+ return HCS_STATUS_ALREADY;
+
+ if (!chan->banned)
+ chan->banned = idb_alloc(DB_OPT_BASE|DB_OPT_ALLOW_NULL_DATA|DB_OPT_RELEASE_DATA);
+
+ CREATE(entry, struct channel_ban_entry, 1);
+ safestrncpy(entry->name, tsd->status.name, NAME_LENGTH);
+ idb_put(chan->banned, tsd->status.account_id, entry);
+
+ channel->leave(chan, tsd);
+
+ return HCS_STATUS_OK;
+}
+
+/**
+ * Unbans a character from the given channel.
+ *
+ * @param chan The channel.
+ * @param ssd The source character, if any.
+ * @param tsd The target character. If no target character is specified, all characters are unbanned.
+ * @retval HCS_STATUS_OK if the operation succeeded.
+ * @retval HCS_STATUS_ALREADY if the target character is not banned.
+ * @retval HCS_STATUS_NOPERM if the source character doesn't have enough permissions.
+ * @retval HCS_STATUS_FAIL in case of generic failure.
+ */
+enum channel_operation_status channel_unban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd)
+{
+ nullpo_retr(HCS_STATUS_FAIL, chan);
+
+ if (ssd && chan->owner != ssd->status.char_id && !pc_has_permission(ssd, PC_PERM_HCHSYS_ADMIN))
+ return HCS_STATUS_NOPERM;
+
+ if (!chan->banned)
+ return HCS_STATUS_ALREADY;
+
+ if (!tsd) {
+ // Unban all
+ db_destroy(chan->banned);
+ chan->banned = NULL;
+ return HCS_STATUS_OK;
+ }
+
+ // Unban one
+ if (!idb_exists(chan->banned, tsd->status.account_id))
+ return HCS_STATUS_ALREADY;
+
+ idb_remove(chan->banned, tsd->status.account_id);
+ if (!db_size(chan->banned)) {
+ db_destroy(chan->banned);
+ chan->banned = NULL;
+ }
+
+ return HCS_STATUS_OK;
+}
+
+/**
+ * Sets or edits a channel's options.
+ *
+ * @param chan The channel.
+ * @param options The new options set to apply.
+ */
+void channel_set_options(struct channel_data *chan, unsigned int options)
+{
+ nullpo_retv(chan);
+
+ chan->options = options;
+}
+
+/**
+ * Sends a message to a channel.
+ *
+ * @param chan The destination channel.
+ * @param sd The source character.
+ * @param msg The message to send.
+ *
+ * If no source character is specified, it'll send an anonymous message.
+ */
+void channel_send(struct channel_data *chan, struct map_session_data *sd, const char *msg)
+{
+ char message[150];
+ nullpo_retv(chan);
+
+ if (sd && chan->msg_delay != 0
+ && DIFF_TICK(sd->hchsysch_tick + chan->msg_delay*1000, timer->gettick()) > 0
+ && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
+ clif->colormes(sd->fd,COLOR_RED,msg_txt(1455));
+ return;
+ } else if (sd) {
+ snprintf(message, 150, "[ #%s ] %s : %s",chan->name,sd->status.name, msg);
+ clif->channel_msg(chan,sd,message);
+ if (chan->type == HCS_TYPE_IRC)
+ ircbot->relay(sd->status.name,msg);
+ if (chan->msg_delay != 0)
+ sd->hchsysch_tick = timer->gettick();
+ } else {
+ snprintf(message, 150, "[ #%s ] %s",chan->name, msg);
+ clif->channel_msg2(chan, message);
+ if (chan->type == HCS_TYPE_IRC)
+ ircbot->relay(NULL, msg);
+ }
+}
+
+/**
+ * Joins a channel, without any permission checks.
+ *
+ * @param chan The channel to join
+ * @param sd The character
+ * @param stealth If true, hide join announcements.
+ */
+void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bool stealth)
+{
+ nullpo_retv(chan);
+ nullpo_retv(sd);
+
+ if (idb_put(chan->users, sd->status.char_id, sd))
+ return;
+
+ RECREATE(sd->channels, struct channel_data *, ++sd->channel_count);
+ sd->channels[sd->channel_count - 1] = chan;
+
+ if (!stealth && (chan->options&HCS_OPT_ANNOUNCE_JOIN)) {
+ char message[60];
+ sprintf(message, "#%s '%s' joined",chan->name,sd->status.name);
+ clif->channel_msg(chan,sd,message);
+ }
+
+ /* someone is cheating, we kindly disconnect the bastard */
+ if (sd->channel_count > 200) {
+ set_eof(sd->fd);
+ }
+
+}
+
+/**
+ * Joins a channel.
+ *
+ * Ban and password checks are performed before joining the channel.
+ * If the channel is an HCS_TYPE_ALLY channel, alliance channels are automatically joined.
+ *
+ * @param chan The channel to join
+ * @param sd The character
+ * @param password The specified join password, if any
+ * @param silent If true, suppress the "You're now in the <x> channel" greeting message
+ * @retval HCS_STATUS_OK if the operation succeeded
+ * @retval HCS_STATUS_ALREADY if the character is already in the channel
+ * @retval HCS_STATUS_NOPERM if the specified password doesn't match
+ * @retval HCS_STATUS_BANNED if the character is in the channel's ban list
+ * @retval HCS_STATUS_FAIL in case of generic error
+ */
+enum channel_operation_status channel_join(struct channel_data *chan, struct map_session_data *sd, const char *password, bool silent)
+{
+ bool stealth = false;
+
+ nullpo_retr(HCS_STATUS_FAIL, chan);
+ nullpo_retr(HCS_STATUS_FAIL, sd);
+
+ if (idb_exists(chan->users, sd->status.char_id)) {
+ return HCS_STATUS_ALREADY;
+ }
+
+ if (chan->password[0] != '\0' && strcmp(chan->password, password) != 0) {
+ if (pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
+ stealth = true;
+ } else {
+ return HCS_STATUS_NOPERM;
+ }
+ }
+
+ if (chan->banned && idb_exists(chan->banned, sd->status.account_id)) {
+ return HCS_STATUS_BANNED;
+ }
+
+ if (!silent && !(chan->options&HCS_OPT_ANNOUNCE_JOIN)) {
+ char output[CHAT_SIZE_MAX];
+ if (chan->type == HCS_TYPE_MAP) {
+ sprintf(output, msg_txt(1435), chan->name, map->list[chan->m].name); // You're now in the '#%s' channel for '%s'
+ } else {
+ sprintf(output, msg_txt(1403), chan->name); // You're now in the '%s' channel
+ }
+ clif->colormes(sd->fd, COLOR_DEFAULT, output);
+ }
+
+ if (chan->type == HCS_TYPE_ALLY) {
+ struct guild *g = sd->guild;
+ int i;
+ for (i = 0; i < MAX_GUILDALLIANCE; i++) {
+ struct guild *sg = NULL;
+ if (g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id))) {
+ if (!(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) {
+ channel->join_sub(sg->channel, sd, stealth);
+ }
+ }
+ }
+ }
+
+ channel->join_sub(chan, sd, stealth);
+
+ return HCS_STATUS_OK;
+}
+
+/**
+ * Removes a channel from a character's join lists.
+ *
+ * @param chan The channel to leave
+ * @param sd The character
+ */
+void channel_leave_sub(struct channel_data *chan, struct map_session_data *sd)
+{
+ unsigned char i;
+
+ nullpo_retv(chan);
+ nullpo_retv(sd);
+ for (i = 0; i < sd->channel_count; i++) {
+ if (sd->channels[i] == chan) {
+ sd->channels[i] = NULL;
+ break;
+ }
+ }
+ if (i < sd->channel_count) {
+ unsigned char cursor = 0;
+ for (i = 0; i < sd->channel_count; i++) {
+ if (sd->channels[i] == NULL)
+ continue;
+ if (cursor != i) {
+ sd->channels[cursor] = sd->channels[i];
+ }
+ cursor++;
+ }
+ if (!(sd->channel_count = cursor)) {
+ aFree(sd->channels);
+ sd->channels = NULL;
+ }
+ }
+}
+/**
+ * Leaves a channel.
+ *
+ * @param chan The channel to leave
+ * @param sd The character
+ */
+void channel_leave(struct channel_data *chan, struct map_session_data *sd)
+{
+ nullpo_retv(chan);
+ nullpo_retv(sd);
+
+ if (!idb_remove(chan->users,sd->status.char_id))
+ return;
+
+ if (chan == sd->gcbind)
+ sd->gcbind = NULL;
+
+ if (!db_size(chan->users) && chan->type == HCS_TYPE_PRIVATE) {
+ channel->delete(chan);
+ } else if (!channel->config->closing && (chan->options & HCS_OPT_ANNOUNCE_JOIN)) {
+ char message[60];
+ sprintf(message, "#%s '%s' left",chan->name,sd->status.name);
+ clif->channel_msg(chan,sd,message);
+ }
+
+ channel->leave_sub(chan, sd);
+}
+
+/**
+ * Quits the channel system.
+ *
+ * Leaves all joined channels.
+ *
+ * @param sd The target character
+ */
+void channel_quit(struct map_session_data *sd)
+{
+ while (sd->channel_count > 0) {
+ // Loop downward to avoid unnecessary array compactions by channel_leave
+ struct channel_data *chan = sd->channels[sd->channel_count-1];
+
+ if (chan == NULL) {
+ sd->channel_count--;
+ continue;
+ }
+
+ channel->leave(chan, sd);
+ }
+}
+
+/**
+ * Joins the local map channel.
+ *
+ * @param sd The target character
+ */
+void channel_map_join(struct map_session_data *sd)
+{
+ if (sd->state.autotrade || sd->state.standalone)
+ return;
+ if (!map->list[sd->bl.m].channel) {
+ if (map->list[sd->bl.m].flag.chsysnolocalaj || (map->list[sd->bl.m].instance_id >= 0 && instance->list[map->list[sd->bl.m].instance_id].owner_type != IOT_NONE))
+ return;
+
+ map->list[sd->bl.m].channel = channel->create(HCS_TYPE_MAP, channel->config->local_name, channel->config->local_color);
+ map->list[sd->bl.m].channel->m = sd->bl.m;
+ }
+
+ channel->join(map->list[sd->bl.m].channel, sd, NULL, false);
+}
+
+/**
+ * Lets a guild's members join a newly allied guild's channel.
+ *
+ * Note: g_source members will join g_ally's channel.
+ * To have g_ally members join g_source's channel, call this function twice, with inverted arguments.
+ *
+ * @param g_source Source guild
+ * @param g_ally Allied guild
+ */
+void channel_guild_join_alliance(const struct guild *g_source, const struct guild *g_ally)
+{
+ struct channel_data *chan;
+
+ nullpo_retv(g_source);
+ nullpo_retv(g_ally);
+
+ if ((chan = g_ally->channel)) {
+ int i;
+ for (i = 0; i < g_source->max_member; i++) {
+ struct map_session_data *sd = g_source->member[i].sd;
+ if (sd == NULL)
+ continue;
+ if (!(g_ally->channel->banned && idb_exists(g_ally->channel->banned, sd->status.account_id)))
+ channel->join_sub(chan,sd, false);
+ }
+ }
+}
+
+/**
+ * Makes a guild's members leave a no former allied guild's channel.
+ *
+ * Note: g_source members will leave g_ally's channel.
+ * To have g_ally members leave g_source's channel, call this function twice, with inverted arguments.
+ *
+ * @param g_source Source guild
+ * @param g_ally Former allied guild
+ */
+void channel_guild_leave_alliance(const struct guild *g_source, const struct guild *g_ally)
+{
+ struct channel_data *chan;
+
+ nullpo_retv(g_source);
+ nullpo_retv(g_ally);
+
+ if ((chan = g_ally->channel)) {
+ int i;
+ for (i = 0; i < g_source->max_member; i++) {
+ struct map_session_data *sd = g_source->member[i].sd;
+ if (sd == NULL)
+ continue;
+
+ channel->leave(chan,sd);
+ }
+ }
+}
+
+/**
+ * Makes a character quit all guild-related channels.
+ *
+ * @param sd The character
+ */
+void channel_quit_guild(struct map_session_data *sd)
+{
+ unsigned char i;
+
+ for (i = 0; i < sd->channel_count; i++) {
+ struct channel_data *chan = sd->channels[i];
+
+ if (chan == NULL || chan->type != HCS_TYPE_ALLY)
+ continue;
+
+ channel->leave(chan, sd);
+ }
+}
+
+void read_channels_config(void)
+{
+ config_t channels_conf;
+ config_setting_t *chsys = NULL;
+ const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name
+
+ if (libconfig->read_file(&channels_conf, config_filename))
+ return;
+
+ chsys = libconfig->lookup(&channels_conf, "chsys");
+
+ if (chsys != NULL) {
+ config_setting_t *settings = libconfig->setting_get_elem(chsys, 0);
+ config_setting_t *channels;
+ config_setting_t *colors;
+ int i,k;
+ const char *local_name, *ally_name,
+ *local_color, *ally_color,
+ *irc_name, *irc_color;
+ int ally_enabled = 0, local_enabled = 0,
+ local_autojoin = 0, ally_autojoin = 0,
+ allow_user_channel_creation = 0,
+ irc_enabled = 0;
+
+ if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) )
+ local_name = "map";
+ safestrncpy(channel->config->local_name, local_name, HCS_NAME_LENGTH);
+
+ if( !libconfig->setting_lookup_string(settings, "ally_channel_name", &ally_name) )
+ ally_name = "ally";
+ safestrncpy(channel->config->ally_name, ally_name, HCS_NAME_LENGTH);
+
+ if( !libconfig->setting_lookup_string(settings, "irc_channel_name", &irc_name) )
+ irc_name = "irc";
+ safestrncpy(channel->config->irc_name, irc_name, HCS_NAME_LENGTH);
+
+ libconfig->setting_lookup_bool(settings, "map_local_channel", &local_enabled);
+ libconfig->setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled);
+ libconfig->setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled);
+
+ if (local_enabled)
+ channel->config->local = true;
+ if (ally_enabled)
+ channel->config->ally = true;
+ if (irc_enabled)
+ channel->config->irc = true;
+
+ channel->config->irc_server[0] = channel->config->irc_channel[0] = channel->config->irc_nick[0] = channel->config->irc_nick_pw[0] = '\0';
+
+ if (channel->config->irc) {
+ const char *irc_server, *irc_channel,
+ *irc_nick, *irc_nick_pw;
+ int irc_use_ghost = 0;
+ if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) {
+ if( !strstr(irc_server,":") ) {
+ channel->config->irc = false;
+ ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
+ } else {
+ unsigned char d = 0, dlen = strlen(irc_server);
+ char server[40];
+ if (dlen > 39)
+ dlen = 39;
+ memset(server, '\0', sizeof(server));
+
+ for(d = 0; d < dlen; d++) {
+ if(irc_server[d] == ':') {
+ memcpy(server, irc_server, d);
+ safestrncpy(channel->config->irc_server, server, 40);
+ memcpy(server, &irc_server[d+1], dlen - d - 1);
+ channel->config->irc_server_port = atoi(server);
+ break;
+ }
+ }
+ }
+ } else {
+ channel->config->irc = false;
+ ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
+ }
+ if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) )
+ safestrncpy(channel->config->irc_channel, irc_channel, 50);
+ else {
+ channel->config->irc = false;
+ ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n");
+ }
+ if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) {
+ if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) {
+ sprintf(channel->config->irc_nick, "Hercules_chSysBot%d",rnd()%777);
+ } else
+ safestrncpy(channel->config->irc_nick, irc_nick, 40);
+ } else {
+ channel->config->irc = false;
+ ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n");
+ }
+ if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) {
+ safestrncpy(channel->config->irc_nick_pw, irc_nick_pw, 30);
+ config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost);
+ channel->config->irc_use_ghost = irc_use_ghost;
+ }
+
+ }
+
+ libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
+ libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
+
+ if (local_autojoin)
+ channel->config->local_autojoin = true;
+ if (ally_autojoin)
+ channel->config->ally_autojoin = true;
+
+ libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
+
+ if( allow_user_channel_creation )
+ channel->config->allow_user_channel_creation = true;
+
+ if( (colors = libconfig->setting_get_member(settings, "colors")) != NULL ) {
+ int color_count = libconfig->setting_length(colors);
+ CREATE(channel->config->colors, unsigned int, color_count);
+ CREATE(channel->config->colors_name, char *, color_count);
+ for(i = 0; i < color_count; i++) {
+ config_setting_t *color = libconfig->setting_get_elem(colors, i);
+
+ CREATE(channel->config->colors_name[i], char, HCS_NAME_LENGTH);
+
+ safestrncpy(channel->config->colors_name[i], config_setting_name(color), HCS_NAME_LENGTH);
+
+ channel->config->colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0);
+ channel->config->colors[i] = (channel->config->colors[i] & 0x0000FF) << 16 | (channel->config->colors[i] & 0x00FF00) | (channel->config->colors[i] & 0xFF0000) >> 16;//RGB to BGR
+ }
+ channel->config->colors_count = color_count;
+ }
+
+ libconfig->setting_lookup_string(settings, "map_local_channel_color", &local_color);
+
+ for (k = 0; k < channel->config->colors_count; k++) {
+ if (strcmpi(channel->config->colors_name[k], local_color) == 0)
+ break;
+ }
+
+ if (k < channel->config->colors_count) {
+ channel->config->local_color = k;
+ } else {
+ ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name);
+ channel->config->local = false;
+ }
+
+ libconfig->setting_lookup_string(settings, "ally_channel_color", &ally_color);
+
+ for (k = 0; k < channel->config->colors_count; k++) {
+ if (strcmpi(channel->config->colors_name[k], ally_color) == 0)
+ break;
+ }
+
+ if( k < channel->config->colors_count ) {
+ channel->config->ally_color = k;
+ } else {
+ ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name);
+ channel->config->ally = false;
+ }
+
+ libconfig->setting_lookup_string(settings, "irc_channel_color", &irc_color);
+
+ for (k = 0; k < channel->config->colors_count; k++) {
+ if (strcmpi(channel->config->colors_name[k], irc_color) == 0)
+ break;
+ }
+
+ if (k < channel->config->colors_count) {
+ channel->config->irc_color = k;
+ } else {
+ ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name);
+ channel->config->irc = false;
+ }
+
+ if (channel->config->irc) {
+ ircbot->channel = channel->create(HCS_TYPE_IRC, channel->config->irc_name, channel->config->irc_color);
+ }
+
+ if( (channels = libconfig->setting_get_member(settings, "default_channels")) != NULL ) {
+ int channel_count = libconfig->setting_length(channels);
+
+ for(i = 0; i < channel_count; i++) {
+ config_setting_t *chan = libconfig->setting_get_elem(channels, i);
+ const char *name = config_setting_name(chan);
+ const char *color = libconfig->setting_get_string_elem(channels,i);
+
+ ARR_FIND(0, channel->config->colors_count, k, strcmpi(channel->config->colors_name[k],color) == 0);
+ if (k == channel->config->colors_count) {
+ ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name);
+ continue;
+ }
+ if (strcmpi(name, channel->config->local_name) == 0
+ || strcmpi(name, channel->config->ally_name) == 0
+ || strcmpi(name, channel->config->irc_name) == 0
+ || strdb_exists(channel->db, name)) {
+ ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name);
+ continue;
+
+ }
+ channel->create(HCS_TYPE_PUBLIC, name, k);
+ }
+ }
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel->db), config_filename);
+ libconfig->destroy(&channels_conf);
+ }
+}
+
+/*==========================================
+ *
+ *------------------------------------------*/
+int do_init_channel(bool minimal)
+{
+ if (minimal)
+ return 0;
+
+ channel->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCS_NAME_LENGTH);
+ channel->config->ally = channel->config->local = channel->config->irc = channel->config->ally_autojoin = channel->config->local_autojoin = false;
+ channel->config_read();
+
+ return 0;
+}
+
+void do_final_channel(void)
+{
+ DBIterator *iter = db_iterator(channel->db);
+ struct channel_data *chan;
+ unsigned char i;
+
+ for( chan = dbi_first(iter); dbi_exists(iter); chan = dbi_next(iter) ) {
+ channel->delete(chan);
+ }
+
+ dbi_destroy(iter);
+
+ for(i = 0; i < channel->config->colors_count; i++) {
+ aFree(channel->config->colors_name[i]);
+ }
+
+ if (channel->config->colors_count) {
+ aFree(channel->config->colors_name);
+ aFree(channel->config->colors);
+ }
+
+ db_destroy(channel->db);
+}
+
+void channel_defaults(void)
+{
+ channel = &channel_s;
+
+ channel->db = NULL;
+ channel->config = &channel_config;
+
+ channel->init = do_init_channel;
+ channel->final = do_final_channel;
+
+ channel->search = channel_search;
+ channel->create = channel_create;
+ channel->delete = channel_delete;
+
+ channel->set_password = channel_set_password;
+ channel->ban = channel_ban;
+ channel->unban = channel_unban;
+ channel->set_options = channel_set_options;
+
+ channel->send = channel_send;
+ channel->join_sub = channel_join_sub;
+ channel->join = channel_join;
+ channel->leave = channel_leave;
+ channel->leave_sub = channel_leave_sub;
+ channel->quit = channel_quit;
+
+ channel->map_join = channel_map_join;
+ channel->guild_join_alliance = channel_guild_join_alliance;
+ channel->guild_leave_alliance = channel_guild_leave_alliance;
+ channel->quit_guild = channel_quit_guild;
+
+ channel->config_read = read_channels_config;
+}
diff --git a/src/map/channel.h b/src/map/channel.h
new file mode 100644
index 000000000..ba6aafc79
--- /dev/null
+++ b/src/map/channel.h
@@ -0,0 +1,119 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef MAP_CHANNEL_H
+#define MAP_CHANNEL_H
+
+#include <stdarg.h>
+
+#include "map.h"
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+
+/**
+ * Declarations
+ **/
+struct map_session_data;
+struct guild;
+
+/**
+ * Defines
+ **/
+#define HCS_NAME_LENGTH 20
+
+enum channel_options {
+ HCS_OPT_BASE = 0x0,
+ HCS_OPT_ANNOUNCE_JOIN = 0x1,
+ HCS_OPT_MSG_DELAY = 0x2,
+};
+
+enum channel_types {
+ HCS_TYPE_PUBLIC = 0,
+ HCS_TYPE_PRIVATE = 1,
+ HCS_TYPE_MAP = 2,
+ HCS_TYPE_ALLY = 3,
+ HCS_TYPE_IRC = 4,
+};
+
+enum channel_operation_status {
+ HCS_STATUS_OK = 0,
+ HCS_STATUS_FAIL,
+ HCS_STATUS_ALREADY,
+ HCS_STATUS_NOPERM,
+ HCS_STATUS_BANNED,
+};
+
+/**
+ * Structures
+ **/
+struct Channel_Config {
+ unsigned int *colors;
+ char **colors_name;
+ unsigned char colors_count;
+ bool local, ally, irc;
+ bool local_autojoin, ally_autojoin;
+ char local_name[HCS_NAME_LENGTH], ally_name[HCS_NAME_LENGTH], irc_name[HCS_NAME_LENGTH];
+ unsigned char local_color, ally_color, irc_color;
+ bool closing;
+ bool allow_user_channel_creation;
+ char irc_server[40], irc_channel[50], irc_nick[40], irc_nick_pw[30];
+ unsigned short irc_server_port;
+ bool irc_use_ghost;
+};
+
+struct channel_ban_entry {
+ char name[NAME_LENGTH];
+};
+
+struct channel_data {
+ char name[HCS_NAME_LENGTH];
+ char password[HCS_NAME_LENGTH];
+ unsigned char color;
+ DBMap *users;
+ DBMap *banned;
+ unsigned int options;
+ unsigned int owner;
+ enum channel_types type;
+ uint16 m;
+ unsigned char msg_delay;
+};
+
+struct channel_interface {
+ /* vars */
+ DBMap *db;
+ struct Channel_Config *config;
+
+ int (*init) (bool minimal);
+ void (*final) (void);
+
+ struct channel_data *(*search) (const char *name, struct map_session_data *sd);
+ struct channel_data *(*create) (enum channel_types type, const char *name, unsigned char color);
+ void (*delete) (struct channel_data *chan);
+
+ void (*set_password) (struct channel_data *chan, const char *password);
+ enum channel_operation_status (*ban) (struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd);
+ enum channel_operation_status (*unban) (struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd);
+ void (*set_options) (struct channel_data *chan, unsigned int options);
+
+ void (*send) (struct channel_data *chan, struct map_session_data *sd, const char *msg);
+ void (*join_sub) (struct channel_data *chan, struct map_session_data *sd, bool stealth);
+ enum channel_operation_status (*join) (struct channel_data *chan, struct map_session_data *sd, const char *password, bool silent);
+ void (*leave) (struct channel_data *chan, struct map_session_data *sd);
+ void (*leave_sub) (struct channel_data *chan, struct map_session_data *sd);
+ void (*quit) (struct map_session_data *sd);
+
+ void (*map_join) (struct map_session_data *sd);
+ void (*guild_join_alliance) (const struct guild *g_source, const struct guild *g_ally);
+ void (*guild_leave_alliance) (const struct guild *g_source, const struct guild *g_ally);
+ void (*quit_guild) (struct map_session_data *sd);
+
+ void (*config_read) (void);
+};
+
+struct channel_interface *channel;
+
+#ifdef HERCULES_CORE
+void channel_defaults(void);
+#endif // HERCULES_CORE
+
+#endif /* MAP_CHANNEL_H */
diff --git a/src/map/clif.c b/src/map/clif.c
index 291b5cb46..269b72ae1 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -16,6 +16,7 @@
#include "atcommand.h"
#include "battle.h"
#include "battleground.h"
+#include "channel.h"
#include "chat.h"
#include "chrif.h"
#include "elemental.h"
@@ -72,8 +73,6 @@ static struct packet_npc_market_open npcmarket_open;
//#define DUMP_UNKNOWN_PACKET
//#define DUMP_INVALID_PACKET
-static struct hChSysConfig clif_hChSys;
-
//Converts item type in case of pet eggs.
static inline int itemtype(int type) {
switch( type ) {
@@ -1833,24 +1832,6 @@ void clif_buylist(struct map_session_data *sd, struct npc_data *nd) {
WFIFOW(fd,2) = 4 + c*11;
WFIFOSET(fd,WFIFOW(fd,2));
}
-void clif_hercules_chsys_create(struct hChSysCh *channel, char *name, char *pass, unsigned char color) {
- channel->users = idb_alloc(DB_OPT_BASE);
- if( name )
- safestrncpy(channel->name, name, HCHSYS_NAME_LENGTH);
- channel->color = color;
- if( !pass )
- channel->pass[0] = '\0';
- else
- safestrncpy(channel->pass, pass, HCHSYS_NAME_LENGTH);
-
- channel->opt = hChSys_OPT_BASE;
- channel->banned = NULL;
-
- channel->msg_delay = 0;
-
- if( channel->type != hChSys_MAP && channel->type != hChSys_ALLY )
- strdb_put(clif->channel_db, channel->name, channel);
-}
/// Presents list of items, that can be sold to an NPC shop (ZC_PC_SELL_ITEMLIST).
/// 00c7 <packet len>.W { <index>.W <price>.L <overcharge price>.L }*
@@ -2116,27 +2097,7 @@ void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, in
WFIFOL(fd,19)=color;
WFIFOSET(fd,packet_len(0x144));
}
-void clif_hercules_chsys_join(struct hChSysCh *channel, struct map_session_data *sd) {
- if( idb_put(channel->users, sd->status.char_id, sd) )
- return;
- RECREATE(sd->channels, struct hChSysCh *, ++sd->channel_count);
- sd->channels[ sd->channel_count - 1 ] = channel;
-
- if( sd->stealth ) {
- sd->stealth = false;
- } else if( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) {
- char message[60];
- sprintf(message, "#%s '%s' joined",channel->name,sd->status.name);
- clif->chsys_msg(channel,sd,message);
- }
-
- /* someone is cheating, we kindly disconnect the bastard */
- if( sd->channel_count > 200 ) {
- set_eof(sd->fd);
- }
-
-}
/// Displays an illustration image.
/// 0145 <image name>.16B <type>.B (ZC_SHOW_IMAGE)
/// 01b3 <image name>.64B <type>.B (ZC_SHOW_IMAGE2)
@@ -2669,225 +2630,6 @@ void clif_guild_xy_remove(struct map_session_data *sd)
WBUFW(buf,8)=-1;
clif->send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS);
}
-void read_channels_config(void) {
- config_t channels_conf;
- config_setting_t *chsys = NULL;
- const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name
-
- if (libconfig->read_file(&channels_conf, config_filename))
- return;
-
- chsys = libconfig->lookup(&channels_conf, "chsys");
-
- if (chsys != NULL) {
- config_setting_t *settings = libconfig->setting_get_elem(chsys, 0);
- config_setting_t *channels;
- config_setting_t *colors;
- int i,k;
- const char *local_name, *ally_name,
- *local_color, *ally_color,
- *irc_name, *irc_color;
- int ally_enabled = 0, local_enabled = 0,
- local_autojoin = 0, ally_autojoin = 0,
- allow_user_channel_creation = 0,
- irc_enabled = 0;
-
- if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) )
- local_name = "map";
- safestrncpy(clif->hChSys->local_name, local_name, HCHSYS_NAME_LENGTH);
-
- if( !libconfig->setting_lookup_string(settings, "ally_channel_name", &ally_name) )
- ally_name = "ally";
- safestrncpy(clif->hChSys->ally_name, ally_name, HCHSYS_NAME_LENGTH);
-
- if( !libconfig->setting_lookup_string(settings, "irc_channel_name", &irc_name) )
- irc_name = "irc";
- safestrncpy(clif->hChSys->irc_name, irc_name, HCHSYS_NAME_LENGTH);
-
- libconfig->setting_lookup_bool(settings, "map_local_channel", &local_enabled);
- libconfig->setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled);
- libconfig->setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled);
-
- if (local_enabled)
- clif->hChSys->local = true;
- if (ally_enabled)
- clif->hChSys->ally = true;
- if (irc_enabled)
- clif->hChSys->irc = true;
-
- clif->hChSys->irc_server[0] = clif->hChSys->irc_channel[0] = clif->hChSys->irc_nick[0] = clif->hChSys->irc_nick_pw[0] = '\0';
-
- if (clif->hChSys->irc) {
- const char *irc_server, *irc_channel,
- *irc_nick, *irc_nick_pw;
- int irc_use_ghost = 0;
- if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) {
- if( !strstr(irc_server,":") ) {
- clif->hChSys->irc = false;
- ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
- } else {
- unsigned char d = 0, dlen = strlen(irc_server);
- char server[40];
- if (dlen > 39)
- dlen = 39;
- memset(server, '\0', sizeof(server));
-
- for(d = 0; d < dlen; d++) {
- if(irc_server[d] == ':') {
- memcpy(server, irc_server, d);
- safestrncpy(clif->hChSys->irc_server, server, 40);
- memcpy(server, &irc_server[d+1], dlen - d - 1);
- clif->hChSys->irc_server_port = atoi(server);
- break;
- }
- }
- }
- } else {
- clif->hChSys->irc = false;
- ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
- }
- if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) )
- safestrncpy(clif->hChSys->irc_channel, irc_channel, 50);
- else {
- clif->hChSys->irc = false;
- ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n");
- }
- if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) {
- if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) {
- sprintf(clif->hChSys->irc_nick, "Hercules_chSysBot%d",rnd()%777);
- } else
- safestrncpy(clif->hChSys->irc_nick, irc_nick, 40);
- } else {
- clif->hChSys->irc = false;
- ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n");
- }
- if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) {
- safestrncpy(clif->hChSys->irc_nick_pw, irc_nick_pw, 30);
- config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost);
- clif->hChSys->irc_use_ghost = irc_use_ghost;
- }
-
- }
-
- libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
- libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
-
- if (local_autojoin)
- clif->hChSys->local_autojoin = true;
- if (ally_autojoin)
- clif->hChSys->ally_autojoin = true;
-
- libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
-
- if( allow_user_channel_creation )
- clif->hChSys->allow_user_channel_creation = true;
-
- if( (colors = libconfig->setting_get_member(settings, "colors")) != NULL ) {
- int color_count = libconfig->setting_length(colors);
- CREATE(clif->hChSys->colors, unsigned int, color_count);
- CREATE(clif->hChSys->colors_name, char *, color_count);
- for(i = 0; i < color_count; i++) {
- config_setting_t *color = libconfig->setting_get_elem(colors, i);
-
- CREATE(clif->hChSys->colors_name[i], char, HCHSYS_NAME_LENGTH);
-
- safestrncpy(clif->hChSys->colors_name[i], config_setting_name(color), HCHSYS_NAME_LENGTH);
-
- clif->hChSys->colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0);
- clif->hChSys->colors[i] = (clif->hChSys->colors[i] & 0x0000FF) << 16 | (clif->hChSys->colors[i] & 0x00FF00) | (clif->hChSys->colors[i] & 0xFF0000) >> 16;//RGB to BGR
- }
- clif->hChSys->colors_count = color_count;
- }
-
- libconfig->setting_lookup_string(settings, "map_local_channel_color", &local_color);
-
- for (k = 0; k < clif->hChSys->colors_count; k++) {
- if (strcmpi(clif->hChSys->colors_name[k], local_color) == 0)
- break;
- }
-
- if (k < clif->hChSys->colors_count) {
- clif->hChSys->local_color = k;
- } else {
- ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name);
- clif->hChSys->local = false;
- }
-
- libconfig->setting_lookup_string(settings, "ally_channel_color", &ally_color);
-
- for (k = 0; k < clif->hChSys->colors_count; k++) {
- if (strcmpi(clif->hChSys->colors_name[k], ally_color) == 0)
- break;
- }
-
- if( k < clif->hChSys->colors_count ) {
- clif->hChSys->ally_color = k;
- } else {
- ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name);
- clif->hChSys->ally = false;
- }
-
- libconfig->setting_lookup_string(settings, "irc_channel_color", &irc_color);
-
- for (k = 0; k < clif->hChSys->colors_count; k++) {
- if (strcmpi(clif->hChSys->colors_name[k], irc_color) == 0)
- break;
- }
-
- if (k < clif->hChSys->colors_count) {
- clif->hChSys->irc_color = k;
- } else {
- ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name);
- clif->hChSys->irc = false;
- }
-
- if (clif->hChSys->irc) {
- struct hChSysCh *chd;
- CREATE(chd, struct hChSysCh, 1);
-
- safestrncpy(chd->name, clif->hChSys->irc_name, HCHSYS_NAME_LENGTH);
- chd->type = hChSys_IRC;
-
- clif->chsys_create(chd, NULL, NULL, clif->hChSys->irc_color);
- ircbot->channel = chd;
- }
-
- if( (channels = libconfig->setting_get_member(settings, "default_channels")) != NULL ) {
- int channel_count = libconfig->setting_length(channels);
-
- for(i = 0; i < channel_count; i++) {
- config_setting_t *channel = libconfig->setting_get_elem(channels, i);
- const char *name = config_setting_name(channel);
- const char *color = libconfig->setting_get_string_elem(channels,i);
- struct hChSysCh *chd;
-
- for (k = 0; k < clif->hChSys->colors_count; k++) {
- if (strcmpi(clif->hChSys->colors_name[k],color) == 0)
- break;
- }
- if( k == clif->hChSys->colors_count) {
- ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name);
- continue;
- }
- if( strcmpi(name, clif->hChSys->local_name) == 0 || strcmpi(name, clif->hChSys->ally_name) == 0 || strcmpi(name, clif->hChSys->irc_name) == 0 || strdb_exists(clif->channel_db, name) ) {
- ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name);
- continue;
-
- }
- CREATE( chd, struct hChSysCh, 1 );
-
- safestrncpy(chd->name, name, HCHSYS_NAME_LENGTH);
- chd->type = hChSys_PUBLIC;
-
- clif->chsys_create(chd,NULL,NULL,k);
- }
- }
-
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(clif->channel_db), config_filename);
- libconfig->destroy(&channels_conf);
- }
-}
-
/*==========================================
*
@@ -3711,21 +3453,6 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok)
}
}
-void clif_hercules_chsys_send(struct hChSysCh *channel, struct map_session_data *sd, const char *msg) {
- if( channel->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + ( channel->msg_delay * 1000 ), timer->gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
- clif->colormes(sd->fd,COLOR_RED,msg_txt(1455));
- return;
- } else {
- char message[150];
- snprintf(message, 150, "[ #%s ] %s : %s",channel->name,sd->status.name, msg);
- clif->chsys_msg(channel,sd,message);
- if( channel->type == hChSys_IRC )
- ircbot->relay(sd->status.name,msg);
- if( channel->msg_delay != 0 )
- sd->hchsysch_tick = timer->gettick();
- }
-}
-
/// Inform client whether chatroom creation was successful or not (ZC_ACK_CREATE_CHATROOM).
/// 00d6 <flag>.B
/// flag:
@@ -9125,8 +8852,9 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_,
return true;
}
-void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *sd, char *msg) {
- DBIterator *iter = db_iterator(channel->users);
+void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg)
+{
+ DBIterator *iter = db_iterator(chan->users);
struct map_session_data *user;
unsigned short msg_len = strlen(msg) + 1;
@@ -9134,10 +8862,10 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *
WFIFOW(sd->fd,0) = 0x2C1;
WFIFOW(sd->fd,2) = msg_len + 12;
WFIFOL(sd->fd,4) = 0;
- WFIFOL(sd->fd,8) = clif->hChSys->colors[channel->color];
+ WFIFOL(sd->fd,8) = channel->config->colors[chan->color];
safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len);
- for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) {
+ for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) {
if( user->fd == sd->fd )
continue;
WFIFOHEAD(user->fd,msg_len + 12);
@@ -9150,8 +8878,9 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *
dbi_destroy(iter);
}
-void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) {
- DBIterator *iter = db_iterator(channel->users);
+void clif_channel_msg2(struct channel_data *chan, char *msg)
+{
+ DBIterator *iter = db_iterator(chan->users);
struct map_session_data *user;
unsigned char buf[210];
unsigned short msg_len = strlen(msg) + 1;
@@ -9159,10 +8888,10 @@ void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) {
WBUFW(buf,0) = 0x2C1;
WBUFW(buf,2) = msg_len + 12;
WBUFL(buf,4) = 0;
- WBUFL(buf,8) = clif->hChSys->colors[channel->color];
+ WBUFL(buf,8) = channel->config->colors[chan->color];
safestrncpy((char*)WBUFP(buf,12), msg, msg_len);
- for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) {
+ for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) {
WFIFOHEAD(user->fd,msg_len + 12);
memcpy(WFIFOP(user->fd,0), WBUFP(buf,0), msg_len + 12);
WFIFOSET(user->fd, msg_len + 12);
@@ -9251,34 +8980,6 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
chrif->authreq(sd,false);
}
-void clif_hercules_chsys_mjoin(struct map_session_data *sd) {
- if( sd->state.autotrade || sd->state.standalone )
- return;
- if( !map->list[sd->bl.m].channel ) {
-
- if (map->list[sd->bl.m].flag.chsysnolocalaj || (map->list[sd->bl.m].instance_id >= 0 && instance->list[map->list[sd->bl.m].instance_id].owner_type != IOT_NONE) )
- return;
-
- CREATE(map->list[sd->bl.m].channel, struct hChSysCh , 1);
- safestrncpy(map->list[sd->bl.m].channel->name, clif->hChSys->local_name, HCHSYS_NAME_LENGTH);
- map->list[sd->bl.m].channel->type = hChSys_MAP;
- map->list[sd->bl.m].channel->m = sd->bl.m;
-
- clif->chsys_create(map->list[sd->bl.m].channel, NULL, NULL, clif->hChSys->local_color);
- }
-
- if( map->list[sd->bl.m].channel->banned && idb_exists(map->list[sd->bl.m].channel->banned, sd->status.account_id) ) {
- return;
- }
-
- clif->chsys_join(map->list[sd->bl.m].channel,sd);
-
- if( !( map->list[sd->bl.m].channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) {
- char mout[60];
- sprintf(mout, msg_txt(1435), clif->hChSys->local_name, map->list[sd->bl.m].name); // You're now in the '#%s' channel for '%s'
- clif->colormes(sd->fd, COLOR_DEFAULT, mout);
- }
-}
/// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT).
/// 007d
@@ -9550,8 +9251,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
status_calc_pc(sd, SCO_NONE);/* some conditions are map-dependent so we must recalculate */
sd->state.changemap = false;
- if (clif->hChSys->local && clif->hChSys->local_autojoin) {
- clif->chsys_mjoin(sd);
+ if (channel->config->local && channel->config->local_autojoin) {
+ channel->map_join(sd);
}
}
@@ -9927,7 +9628,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
sd->idletime = sockt->last_tick;
if( sd->gcbind ) {
- clif->chsys_send(sd->gcbind,sd,message);
+ channel->send(sd->gcbind,sd,message);
return;
} else if ( sd->fontcolor && !sd->chatID ) {
char mout[200];
@@ -9953,7 +9654,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = mylen + 12;
WFIFOL(fd,4) = sd->bl.id;
- WFIFOL(fd,8) = clif->hChSys->colors[sd->fontcolor - 1];
+ WFIFOL(fd,8) = channel->config->colors[sd->fontcolor - 1];
safestrncpy((char*)WFIFOP(fd,12), mout, mylen);
clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS);
WFIFOL(fd,4) = -sd->bl.id;
@@ -10219,117 +9920,6 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
}
}
-void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data *sd) {
- unsigned char i;
-
- if ( !idb_remove(channel->users,sd->status.char_id) )
- return;
-
- if( channel == sd->gcbind )
- sd->gcbind = NULL;
-
- if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) {
- clif->chsys_delete(channel);
- } else if( !clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
- char message[60];
- sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
- clif->chsys_msg(channel,sd,message);
- }
-
- for( i = 0; i < sd->channel_count; i++ ) {
- if( sd->channels[i] == channel ) {
- sd->channels[i] = NULL;
- break;
- }
- }
-
- if( i < sd->channel_count ) {
- unsigned char cursor = 0;
- for( i = 0; i < sd->channel_count; i++ ) {
- if( sd->channels[i] == NULL )
- continue;
- if( cursor != i ) {
- sd->channels[cursor] = sd->channels[i];
- }
- cursor++;
- }
- if ( !(sd->channel_count = cursor) ) {
- aFree(sd->channels);
- sd->channels = NULL;
- }
- }
-
-}
-
-void clif_hercules_chsys_quitg(struct map_session_data *sd) {
- unsigned char i;
-
- for( i = 0; i < sd->channel_count; i++ ) {
- struct hChSysCh *channel = sd->channels[i];
- if (channel != NULL && channel->type == hChSys_ALLY) {
- if (!idb_remove(channel->users,sd->status.char_id))
- continue;
-
- if( channel == sd->gcbind )
- sd->gcbind = NULL;
-
- if (!db_size(channel->users) && channel->type == hChSys_PRIVATE) {
- clif->chsys_delete(channel);
- } else if (!clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) {
- char message[60];
- sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
- clif->chsys_msg(channel,sd,message);
- }
- sd->channels[i] = NULL;
- }
- }
-
- if( i < sd->channel_count ) {
- unsigned char cursor = 0;
- for( i = 0; i < sd->channel_count; i++ ) {
- if( sd->channels[i] == NULL )
- continue;
- if( cursor != i ) {
- sd->channels[cursor] = sd->channels[i];
- }
- cursor++;
- }
- if ( !(sd->channel_count = cursor) ) {
- aFree(sd->channels);
- sd->channels = NULL;
- }
- }
-
-}
-
-
-void clif_hercules_chsys_quit(struct map_session_data *sd) {
- unsigned char i;
-
- for (i = 0; i < sd->channel_count; i++) {
- struct hChSysCh *channel = sd->channels[i];
- if (channel != NULL) {
- idb_remove(channel->users,sd->status.char_id);
-
- if( channel == sd->gcbind )
- sd->gcbind = NULL;
-
- if (!db_size(channel->users) && channel->type == hChSys_PRIVATE) {
- clif->chsys_delete(channel);
- } else if (!clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) {
- char message[60];
- sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
- clif->chsys_msg(channel,sd,message);
- }
-
- }
- }
-
- sd->channel_count = 0;
- aFree(sd->channels);
- sd->channels = NULL;
-}
-
/// Request for an action.
/// 0089 <target id>.L <action>.B (CZ_REQUEST_ACT)
/// 0437 <target id>.L <action>.B (CZ_REQUEST_ACT2)
@@ -10450,42 +10040,14 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
return;
}
} else if( target[0] == '#' ) {
- struct hChSysCh *channel = NULL;
- char* chname = target;
+ char *chname = target;
+ struct channel_data *chan = channel->search(chname, sd);
- chname++;
-
- if (clif->hChSys->local && strcmpi(chname, clif->hChSys->local_name) == 0) {
- if( !map->list[sd->bl.m].channel ) {
- clif->chsys_mjoin(sd);
- }
- channel = map->list[sd->bl.m].channel;
- } else if (clif->hChSys->ally && sd->status.guild_id && strcmpi(chname, clif->hChSys->ally_name) == 0) {
- struct guild *g = sd->guild;
- if( !g ) return;
- channel = g->channel;
- }
- if( channel || (channel = strdb_get(clif->channel_db,chname)) ) {
+ if (chan) {
int k;
- for( k = 0; k < sd->channel_count; k++ ) {
- if( sd->channels[k] == channel )
- break;
- }
- if( k < sd->channel_count ) {
- clif->chsys_send(channel,sd,message);
- } else if( channel->pass[0] == '\0' && !(channel->banned && idb_exists(channel->banned, sd->status.account_id)) ) {
- if( channel->type == hChSys_ALLY ) {
- struct guild *g = sd->guild;
- for (k = 0; k < MAX_GUILDALLIANCE; k++) {
- struct guild *sg = NULL;
- if( g->alliance[k].opposition == 0 && g->alliance[k].guild_id && (sg = guild->search(g->alliance[k].guild_id) ) ) {
- if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id)))
- clif->chsys_join(sg->channel,sd);
- }
- }
- }
- clif->chsys_join(channel,sd);
- clif->chsys_send(channel,sd,message);
+ ARR_FIND(0, sd->channel_count, k, sd->channels[k] == chan);
+ if (k < sd->channel_count || channel->join(chan, sd, NULL, true) == HCS_STATUS_OK) {
+ channel->send(chan,sd,message);
} else {
clif->message(fd, msg_txt(1402));
}
@@ -10711,95 +10273,6 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) {
pc->equipitem(sd,p->index,p->wearLocation);
}
-void clif_hercules_chsys_delete(struct hChSysCh *channel) {
- if (db_size(channel->users) && !clif->hChSys->closing) {
- DBIterator *iter;
- struct map_session_data *sd;
- unsigned char i;
- iter = db_iterator(channel->users);
- for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) {
- for( i = 0; i < sd->channel_count; i++ ) {
- if( sd->channels[i] == channel ) {
- sd->channels[i] = NULL;
- break;
- }
- }
- if( i < sd->channel_count ) {
- unsigned char cursor = 0;
- for( i = 0; i < sd->channel_count; i++ ) {
- if( sd->channels[i] == NULL )
- continue;
- if( cursor != i ) {
- sd->channels[cursor] = sd->channels[i];
- }
- cursor++;
- }
- if ( !(sd->channel_count = cursor) ) {
- aFree(sd->channels);
- sd->channels = NULL;
- }
- }
- }
- dbi_destroy(iter);
- }
- if( channel->banned ) {
- db_destroy(channel->banned);
- channel->banned = NULL;
- }
- db_destroy(channel->users);
- if( channel->m ) {
- map->list[channel->m].channel = NULL;
- aFree(channel);
- } else if ( channel->type == hChSys_ALLY )
- aFree(channel);
- else if (!clif->hChSys->closing)
- strdb_remove(clif->channel_db, channel->name);
-}
-void clif_hercules_chsys_gjoin(struct guild *g1,struct guild *g2) {
- struct map_session_data *sd;
- struct hChSysCh *channel;
- int j;
-
- if( (channel = g1->channel) ) {
- for(j = 0; j < g2->max_member; j++) {
- if( (sd = g2->member[j].sd) != NULL ) {
- if( !(g1->channel->banned && idb_exists(g1->channel->banned, sd->status.account_id)))
- clif->chsys_join(channel,sd);
- }
- }
- }
-
- if( (channel = g2->channel) ) {
- for(j = 0; j < g1->max_member; j++) {
- if( (sd = g1->member[j].sd) != NULL ) {
- if( !(g2->channel->banned && idb_exists(g2->channel->banned, sd->status.account_id)))
- clif->chsys_join(channel,sd);
- }
- }
- }
-}
-void clif_hercules_chsys_gleave(struct guild *g1,struct guild *g2) {
- struct map_session_data *sd;
- struct hChSysCh *channel;
- int j;
-
- if( (channel = g1->channel) ) {
- for(j = 0; j < g2->max_member; j++) {
- if( (sd = g2->member[j].sd) != NULL ) {
- clif->chsys_left(channel,sd);
- }
- }
- }
-
- if( (channel = g2->channel) ) {
- for(j = 0; j < g1->max_member; j++) {
- if( (sd = g1->member[j].sd) != NULL ) {
- clif->chsys_left(channel,sd);
- }
- }
- }
-}
-
/// Request to take off an equip (CZ_REQ_TAKEOFF_EQUIP).
/// 00ab <index>.W
void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
@@ -18899,34 +18372,13 @@ int do_init_clif(bool minimal) {
clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR);
clif->delayed_damage_ers = ers_new(sizeof(struct cdelayed_damage),"clif.c::delayed_damage_ers",ERS_OPT_CLEAR);
- clif->channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCHSYS_NAME_LENGTH);
- clif->hChSys->ally = clif->hChSys->local = clif->hChSys->irc = clif->hChSys->ally_autojoin = clif->hChSys->local_autojoin = false;
- clif->chann_config_read();
-
return 0;
}
-void do_final_clif(void) {
- DBIterator *iter = db_iterator(clif->channel_db);
- struct hChSysCh *channel;
+void do_final_clif(void)
+{
unsigned char i;
- for( channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter) ) {
- clif->chsys_delete(channel);
- }
-
- dbi_destroy(iter);
-
- for(i = 0; i < clif->hChSys->colors_count; i++) {
- aFree(clif->hChSys->colors_name[i]);
- }
-
- if (clif->hChSys->colors_count) {
- aFree(clif->hChSys->colors_name);
- aFree(clif->hChSys->colors);
- }
-
- db_destroy(clif->channel_db);
ers_destroy(clif->delay_clearunit_ers);
ers_destroy(clif->delayed_damage_ers);
@@ -19420,21 +18872,11 @@ void clif_defaults(void) {
clif->user_count = clif_user_count;
clif->noask_sub = clif_noask_sub;
clif->bc_ready = clif_bc_ready;
- clif->undisguise_timer = clif_undisguise_timer;
/* Hercules Channel System */
- clif->hChSys = &clif_hChSys;
- clif->chsys_create = clif_hercules_chsys_create;
- clif->chsys_msg = clif_hercules_chsys_msg;
- clif->chsys_msg2 = clif_hercules_chsys_msg2;
- clif->chsys_send = clif_hercules_chsys_send;
- clif->chsys_join = clif_hercules_chsys_join;
- clif->chsys_left = clif_hercules_chsys_left;
- clif->chsys_delete = clif_hercules_chsys_delete;
- clif->chsys_mjoin = clif_hercules_chsys_mjoin;
- clif->chsys_quit = clif_hercules_chsys_quit;
- clif->chsys_quitg = clif_hercules_chsys_quitg;
- clif->chsys_gjoin = clif_hercules_chsys_gjoin;
- clif->chsys_gleave = clif_hercules_chsys_gleave;
+ clif->channel_msg = clif_channel_msg;
+ clif->channel_msg2 = clif_channel_msg2;
+ /* */
+ clif->undisguise_timer = clif_undisguise_timer;
/* Bank System [Yommy/Hercules] */
clif->bank_deposit = clif_bank_deposit;
clif->bank_withdraw = clif_bank_withdraw;
@@ -19488,7 +18930,6 @@ void clif_defaults(void) {
clif->pKickFromChat = clif_parse_KickFromChat;
clif->pChatLeave = clif_parse_ChatLeave;
clif->pTradeRequest = clif_parse_TradeRequest;
- clif->chann_config_read = read_channels_config;
clif->pTradeAck = clif_parse_TradeAck;
clif->pTradeAddItem = clif_parse_TradeAddItem;
clif->pTradeOk = clif_parse_TradeOk;
diff --git a/src/map/clif.h b/src/map/clif.h
index 6a99ba79a..5f1a2a899 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -38,6 +38,7 @@ struct party_booking_ad_info;
struct view_data;
struct eri;
struct skill_cd;
+struct channel_data;
/**
* Defines
@@ -47,7 +48,6 @@ struct skill_cd;
#define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0)
#define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF )
#define clif_viewequip_fail( sd ) clif->msg( (sd), 0x54d );
-#define HCHSYS_NAME_LENGTH 20
#define MAX_ROULETTE_LEVEL 7 /** client-defined value **/
#define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/
@@ -375,20 +375,6 @@ enum clif_colors {
COLOR_MAX
};
-enum hChSysChOpt {
- hChSys_OPT_BASE = 0x0,
- hChSys_OPT_ANNOUNCE_JOIN = 0x1,
- hChSys_OPT_MSG_DELAY = 0x2,
-};
-
-enum hChSysChType {
- hChSys_PUBLIC = 0,
- hChSys_PRIVATE = 1,
- hChSys_MAP = 2,
- hChSys_ALLY = 3,
- hChSys_IRC = 4,
-};
-
enum CASH_SHOP_TABS {
CASHSHOP_TAB_NEW = 0,
CASHSHOP_TAB_POPULAR = 1,
@@ -518,38 +504,6 @@ struct s_packet_db {
short pos[MAX_PACKET_POS];
};
-struct hChSysConfig {
- unsigned int *colors;
- char **colors_name;
- unsigned char colors_count;
- bool local, ally, irc;
- bool local_autojoin, ally_autojoin;
- char local_name[HCHSYS_NAME_LENGTH], ally_name[HCHSYS_NAME_LENGTH], irc_name[HCHSYS_NAME_LENGTH];
- unsigned char local_color, ally_color, irc_color;
- bool closing;
- bool allow_user_channel_creation;
- char irc_server[40], irc_channel[50], irc_nick[40], irc_nick_pw[30];
- unsigned short irc_server_port;
- bool irc_use_ghost;
-};
-
-struct hChSysBanEntry {
- char name[NAME_LENGTH];
-};
-
-struct hChSysCh {
- char name[HCHSYS_NAME_LENGTH];
- char pass[HCHSYS_NAME_LENGTH];
- unsigned char color;
- DBMap *users;
- DBMap *banned;
- unsigned int opt;
- unsigned int owner;
- enum hChSysChType type;
- uint16 m;
- unsigned char msg_delay;
-};
-
struct hCSData {
unsigned short id;
unsigned int price;
@@ -576,8 +530,6 @@ struct clif_interface {
uint16 map_port;
char map_ip_str[128];
int map_fd;
- DBMap* channel_db;
- struct hChSysConfig *hChSys;
/* for clif_clearunit_delayed */
struct eri *delay_clearunit_ers;
/* Cash Shop [Ind/Hercules] */
@@ -1065,20 +1017,10 @@ struct clif_interface {
void (*user_count) (struct map_session_data* sd, int count);
void (*noask_sub) (struct map_session_data *src, struct map_session_data *target, int type);
void (*bc_ready) (void);
- int (*undisguise_timer) (int tid, int64 tick, int id, intptr_t data);
/* Hercules Channel System */
- void (*chsys_create) (struct hChSysCh *channel, char *name, char *pass, unsigned char color);
- void (*chsys_msg) (struct hChSysCh *channel, struct map_session_data *sd, char *msg);
- void (*chsys_msg2) (struct hChSysCh *channel, char *msg);
- void (*chsys_send) (struct hChSysCh *channel, struct map_session_data *sd, const char *msg);
- void (*chsys_join) (struct hChSysCh *channel, struct map_session_data *sd);
- void (*chsys_left) (struct hChSysCh *channel, struct map_session_data *sd);
- void (*chsys_delete) (struct hChSysCh *channel);
- void (*chsys_mjoin) (struct map_session_data *sd);
- void (*chsys_quit) (struct map_session_data *sd);
- void (*chsys_quitg) (struct map_session_data *sd);
- void (*chsys_gjoin) (struct guild *g1,struct guild *g2);
- void (*chsys_gleave) (struct guild *g1,struct guild *g2);
+ void (*channel_msg) (struct channel_data *chan, struct map_session_data *sd, char *msg);
+ void (*channel_msg2) (struct channel_data *chan, char *msg);
+ int (*undisguise_timer) (int tid, int64 tick, int id, intptr_t data);
/* Bank System [Yommy/Hercules] */
void (*bank_deposit) (struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason);
void (*bank_withdraw) (struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason);
@@ -1132,7 +1074,6 @@ struct clif_interface {
void (*pKickFromChat) (int fd,struct map_session_data *sd);
void (*pChatLeave) (int fd, struct map_session_data* sd);
void (*pTradeRequest) (int fd,struct map_session_data *sd);
- void (*chann_config_read) (void);
void (*pTradeAck) (int fd,struct map_session_data *sd);
void (*pTradeAddItem) (int fd,struct map_session_data *sd);
void (*pTradeOk) (int fd,struct map_session_data *sd);
diff --git a/src/map/guild.c b/src/map/guild.c
index 913bd0e4a..7f116bae1 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -12,6 +12,7 @@
#include <string.h>
#include "battle.h"
+#include "channel.h"
#include "clif.h"
#include "instance.h"
#include "intif.h"
@@ -458,7 +459,7 @@ int guild_recv_info(struct guild *sg) {
DBData data;
struct map_session_data *sd;
bool guild_new = false;
- struct hChSysCh *aChSysSave = NULL;
+ struct channel_data *aChSysSave = NULL;
short *instance_save = NULL;
unsigned short instances_save = 0;
@@ -470,15 +471,9 @@ int guild_recv_info(struct guild *sg) {
g->instance = NULL;
g->instances = 0;
idb_put(guild->db,sg->guild_id,g);
- if (clif->hChSys->ally) {
- struct hChSysCh *channel;
-
- CREATE(channel, struct hChSysCh , 1);
- safestrncpy(channel->name, clif->hChSys->ally_name, HCHSYS_NAME_LENGTH);
- channel->type = hChSys_ALLY;
-
- clif->chsys_create(channel, NULL, NULL, clif->hChSys->ally_color);
- if (clif->hChSys->ally_autojoin) {
+ if (channel->config->ally) {
+ struct channel_data *chan = channel->create(HCS_TYPE_ALLY, channel->config->ally_name, channel->config->ally_color);
+ if (channel->config->ally_autojoin) {
struct s_mapiterator* iter = mapit_getallusers();
struct guild *tg[MAX_GUILDALLIANCE];
@@ -494,13 +489,13 @@ int guild_recv_info(struct guild *sg) {
if (sd->status.guild_id == sg->guild_id) {
// Guild member
- clif->chsys_join(channel,sd);
+ channel->join_sub(chan,sd,false);
sd->guild = g;
for (i = 0; i < MAX_GUILDALLIANCE; i++) {
// Join channels from allied guilds
if (tg[i] && !(tg[i]->channel->banned && idb_exists(tg[i]->channel->banned, sd->status.account_id)))
- clif->chsys_join(tg[i]->channel, sd);
+ channel->join_sub(tg[i]->channel, sd, false);
}
continue;
}
@@ -508,8 +503,8 @@ int guild_recv_info(struct guild *sg) {
for (i = 0; i < MAX_GUILDALLIANCE; i++) {
if (tg[i] && sd->status.guild_id == tg[i]->guild_id) { // Shortcut to skip the alliance checks again
// Alliance member
- if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id)))
- clif->chsys_join(channel, sd);
+ if( !(chan->banned && idb_exists(chan->banned, sd->status.account_id)))
+ channel->join_sub(chan, sd, false);
}
}
}
@@ -518,7 +513,7 @@ int guild_recv_info(struct guild *sg) {
}
- aChSysSave = channel;
+ aChSysSave = chan;
}
before=*sg;
@@ -745,18 +740,8 @@ void guild_member_joined(struct map_session_data *sd)
g->member[i].sd = sd;
sd->guild = g;
- if (clif->hChSys->ally && clif->hChSys->ally_autojoin) {
- struct hChSysCh *channel = g->channel;
-
- if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id) ) )
- clif->chsys_join(channel,sd);
- for (i = 0; i < MAX_GUILDALLIANCE; i++) {
- struct guild* sg = NULL;
- if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) {
- if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id)))
- clif->chsys_join(sg->channel,sd);
- }
- }
+ if (channel->config->ally && channel->config->ally_autojoin) {
+ channel->join(g->channel, sd, NULL, true);
}
}
@@ -913,8 +898,8 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
if (sd->state.storage_flag == 2) //Close the guild storage.
gstorage->close(sd);
guild->send_dot_remove(sd);
- if (clif->hChSys->ally) {
- clif->chsys_quitg(sd);
+ if (channel->config->ally) {
+ channel->quit_guild(sd);
}
sd->status.guild_id = 0;
sd->guild = NULL;
@@ -1646,12 +1631,15 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
return 0;
}
- if (g[0] && g[1] && clif->hChSys->ally && ( flag & 1 ) == 0) {
+ if (g[0] && g[1] && channel->config->ally && ( flag & 1 ) == 0) {
if( !(flag & 0x08) ) {
- if (clif->hChSys->ally_autojoin)
- clif->chsys_gjoin(g[0],g[1]);
+ if (channel->config->ally_autojoin) {
+ channel->guild_join_alliance(g[0],g[1]);
+ channel->guild_join_alliance(g[1],g[0]);
+ }
} else {
- clif->chsys_gleave(g[0],g[1]);
+ channel->guild_leave_alliance(g[0],g[1]);
+ channel->guild_leave_alliance(g[1],g[0]);
}
}
@@ -1779,9 +1767,9 @@ int guild_broken(int guild_id,int flag)
guild->db->foreach(guild->db,guild->broken_sub,guild_id);
guild->castle_db->foreach(guild->castle_db,guild->castle_broken_sub,guild_id);
gstorage->delete(guild_id);
- if (clif->hChSys->ally) {
+ if (channel->config->ally) {
if( g->channel != NULL ) {
- clif->chsys_delete(g->channel);
+ channel->delete(g->channel);
}
}
if( g->instance )
@@ -2280,7 +2268,7 @@ void do_final_guild(void) {
for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) {
if( g->channel != NULL )
- clif->chsys_delete(g->channel);
+ channel->delete(g->channel);
if( g->instance != NULL ) {
aFree(g->instance);
g->instance = NULL;
diff --git a/src/map/instance.c b/src/map/instance.c
index a2d363fc9..dd5709452 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -13,6 +13,7 @@
#include <time.h>
#include "../config/core.h" // CELL_NOSTACK
+#include "channel.h"
#include "clif.h"
#include "map.h"
#include "npc.h"
@@ -483,7 +484,7 @@ void instance_del_map(int16 m) {
ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map->list[m].name, instance->list[map->list[m].instance_id].name, m);
if( map->list[m].channel )
- clif->chsys_delete(map->list[m].channel);
+ channel->delete(map->list[m].channel);
map->removemapdb(&map->list[m]);
memset(&map->list[m], 0x00, sizeof(map->list[0]));
diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c
index 36c19ccbd..d492ad9ca 100644
--- a/src/map/irc-bot.c
+++ b/src/map/irc-bot.c
@@ -10,7 +10,7 @@
#include <stdlib.h>
#include <string.h>
-#include "clif.h"
+#include "channel.h"
#include "map.h"
#include "pc.h"
#include "../common/cbasetypes.h"
@@ -41,7 +41,7 @@ int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) {
ircbot->last_try = timer->gettick();
- if ((ircbot->fd = make_connection(ircbot->ip, clif->hChSys->irc_server_port, &opt)) > 0) {
+ if ((ircbot->fd = make_connection(ircbot->ip, channel->config->irc_server_port, &opt)) > 0) {
session[ircbot->fd]->func_parse = ircbot->parse;
session[ircbot->fd]->flag.server = 1;
timer->add(timer->gettick() + 3000, ircbot->identify_timer, 0, 0);
@@ -60,7 +60,7 @@ int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) {
sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rnd()%777);
ircbot->send(send_string);
- sprintf(send_string, "NICK %s", clif->hChSys->irc_nick);
+ sprintf(send_string, "NICK %s", channel->config->irc_nick);
ircbot->send(send_string);
timer->add(timer->gettick() + 3000, ircbot->join_timer, 0, 0);
@@ -76,15 +76,15 @@ int irc_join_timer(int tid, int64 tick, int id, intptr_t data) {
if( !ircbot->isOn )
return 0;
- if (clif->hChSys->irc_nick_pw[0] != '\0') {
- sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", clif->hChSys->irc_nick_pw);
+ if (channel->config->irc_nick_pw[0] != '\0') {
+ sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", channel->config->irc_nick_pw);
ircbot->send(send_string);
- if (clif->hChSys->irc_use_ghost) {
- sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", clif->hChSys->irc_nick, clif->hChSys->irc_nick_pw);
+ if (channel->config->irc_use_ghost) {
+ sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", channel->config->irc_nick, channel->config->irc_nick_pw);
}
}
- sprintf(send_string, "JOIN %s", clif->hChSys->irc_channel);
+ sprintf(send_string, "JOIN %s", channel->config->irc_channel);
ircbot->send(send_string);
ircbot->isIn = true;
@@ -120,7 +120,7 @@ int irc_parse(int fd) {
ircbot->isOn = false;
ircbot->isIn = false;
ircbot->fails = 0;
- ircbot->ip = host2ip(clif->hChSys->irc_server);
+ ircbot->ip = host2ip(channel->config->irc_server);
timer->add(timer->gettick() + 120000, ircbot->connect_timer, 0, 0);
return 0;
}
@@ -243,7 +243,7 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
if( strcmpi(cmd,"ACTION") == 0 ) {
if( ircbot->channel ) {
snprintf(send_string, 150, "[ #%s ] * IRC.%s %s *",ircbot->channel->name,source_nick,msg);
- clif->chsys_msg2(ircbot->channel,send_string);
+ clif->channel_msg2(ircbot->channel,send_string);
}
} else if( strcmpi(cmd,"ERRMSG") == 0 ) {
// Ignore it
@@ -290,10 +290,10 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
irc_privmsg_ctcp(fd, command, source, target, message);
#ifdef IRCBOT_DEBUG
- } else if (strcmpi(target, clif->hChSys->irc_nick) == 0) {
+ } else if (strcmpi(target, channel->config->irc_nick) == 0) {
ShowDebug("irc_privmsg: Received message from %s: '%s'\n", source ? source : "(null)", msg);
#endif // IRCBOT_DEBUG
- } else if (msg && strcmpi(target, clif->hChSys->irc_channel) == 0) {
+ } else if (msg && strcmpi(target, channel->config->irc_channel) == 0) {
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
source_nick[0] = source_ident[0] = source_host[0] = '\0';
@@ -305,7 +305,7 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
size_t padding_len = strlen(ircbot->channel->name) + strlen(source_nick) + 13;
while (1) {
snprintf(send_string, 150, "[ #%s ] IRC.%s : %s",ircbot->channel->name,source_nick,msg);
- clif->chsys_msg2(ircbot->channel,send_string);
+ clif->channel_msg2(ircbot->channel,send_string);
//break; // Uncomment this line to truncate long messages instead of posting them as multiple lines
if (strlen(msg) <= 149 - padding_len)
break;
@@ -330,7 +330,7 @@ void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg) {
if( ircbot->channel ) {
snprintf(send_string, 150, "[ #%s ] User IRC.%s joined the channel.",ircbot->channel->name,source_nick);
- clif->chsys_msg2(ircbot->channel,send_string);
+ clif->channel_msg2(ircbot->channel,send_string);
}
}
@@ -352,7 +352,7 @@ void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg) {
snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [Quit: %s]",ircbot->channel->name,source_nick,msg);
else
snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [%s]",ircbot->channel->name,source_nick,msg);
- clif->chsys_msg2(ircbot->channel,send_string);
+ clif->channel_msg2(ircbot->channel,send_string);
}
}
@@ -371,7 +371,7 @@ void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
if( ircbot->channel ) {
snprintf(send_string, 150, "[ #%s ] User IRC.%s is now known as IRC.%s",ircbot->channel->name,source_nick,msg);
- clif->chsys_msg2(ircbot->channel,send_string);
+ clif->channel_msg2(ircbot->channel,send_string);
}
}
@@ -380,10 +380,16 @@ void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
* @param name Sender's name
* @param msg Message text
*/
-void irc_relay(char *name, const char *msg) {
- if( !ircbot->isIn )
+void irc_relay(const char *name, const char *msg)
+{
+ if (!ircbot->isIn)
return;
- sprintf(send_string,"PRIVMSG %s :[ %s ] : %s", clif->hChSys->irc_channel, name, msg);
+
+ if (name)
+ sprintf(send_string,"PRIVMSG %s :[ %s ] : %s", channel->config->irc_channel, name, msg);
+ else
+ sprintf(send_string,"PRIVMSG %s :%s", channel->config->irc_channel, msg);
+
ircbot->send(send_string);
}
@@ -406,12 +412,12 @@ void irc_bot_init(bool minimal) {
if (minimal)
return;
- if (!clif->hChSys->irc)
+ if (!channel->config->irc)
return;
- if (!(ircbot->ip = host2ip(clif->hChSys->irc_server))) {
- ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", clif->hChSys->irc_server);
- clif->hChSys->irc = false;
+ if (!(ircbot->ip = host2ip(channel->config->irc_server))) {
+ ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", channel->config->irc_server);
+ channel->config->irc = false;
return;
}
@@ -444,7 +450,7 @@ void irc_bot_init(bool minimal) {
void irc_bot_final(void) {
int i;
- if (!clif->hChSys->irc)
+ if (!channel->config->irc)
return;
if( ircbot->isOn ) {
ircbot->send("QUIT :Hercules is shutting down");
diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h
index 23c2fabc8..8dcfea5bd 100644
--- a/src/map/irc-bot.h
+++ b/src/map/irc-bot.h
@@ -14,7 +14,7 @@
#define IRC_FUNC_LENGTH 30
#define IRC_MESSAGE_LENGTH 500
-struct hChSysCh;
+struct channel_data;
struct irc_func {
char name[IRC_FUNC_LENGTH];
@@ -29,7 +29,7 @@ struct irc_bot_interface {
uint32 ip;
unsigned short port;
/* */
- struct hChSysCh *channel;
+ struct channel_data *channel;
/* */
struct {
struct irc_func **list;
@@ -50,7 +50,7 @@ struct irc_bot_interface {
int (*join_timer) (int tid, int64 tick, int id, intptr_t data);
/* */
void (*send)(char *str);
- void (*relay) (char *name, const char *msg);
+ void (*relay) (const char *name, const char *msg);
/* */
void (*pong) (int fd, char *cmd, char *source, char *target, char *msg);
void (*privmsg) (int fd, char *cmd, char *source, char *target, char *msg);
diff --git a/src/map/map.c b/src/map/map.c
index ae31f01ec..1f893269b 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -17,6 +17,7 @@
#include "atcommand.h"
#include "battle.h"
#include "battleground.h"
+#include "channel.h"
#include "chat.h"
#include "chrif.h"
#include "clif.h"
@@ -1799,7 +1800,7 @@ int map_quit(struct map_session_data *sd) {
if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */
bg->team_leave(sd,BGTL_QUIT);
- if (sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !clif->hChSys->closing)
+ if (sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !channel->config->closing)
pc->autotrade_update(sd,PAUC_REMOVE);
skill->cooldown_save(sd);
@@ -1856,11 +1857,7 @@ int map_quit(struct map_session_data *sd) {
unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK);
}
- if (clif->hChSys->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) {
- clif->chsys_left(map->list[sd->bl.m].channel,sd);
- }
-
- clif->chsys_quit(sd);
+ channel->quit(sd);
unit->remove_map_pc(sd,CLR_RESPAWN);
@@ -3189,7 +3186,7 @@ void map_clean(int i) {
}
if( map->list[i].channel )
- clif->chsys_delete(map->list[i].channel);
+ channel->delete(map->list[i].channel);
}
void do_final_maps(void) {
int i, v = 0;
@@ -3248,7 +3245,7 @@ void do_final_maps(void) {
aFree(map->list[i].drop_list);
if( map->list[i].channel )
- clif->chsys_delete(map->list[i].channel);
+ channel->delete(map->list[i].channel);
if( map->list[i].qi_data )
aFree(map->list[i].qi_data);
@@ -5356,7 +5353,7 @@ int do_final(void) {
ShowStatus("Terminating...\n");
- clif->hChSys->closing = true;
+ channel->config->closing = true;
HPM->event(HPET_FINAL);
if (map->cpsd) aFree(map->cpsd);
@@ -5392,8 +5389,9 @@ int do_final(void) {
atcommand->final();
battle->final();
+ ircbot->final();/* before channel. */
+ channel->final();
chrif->final();
- ircbot->final();/* before clif. */
clif->final();
npc->final();
quest->final();
@@ -5579,6 +5577,7 @@ void map_hp_symbols(void) {
HPM->share(battle,"battle");
HPM->share(bg,"battlegrounds");
HPM->share(buyingstore,"buyingstore");
+ HPM->share(channel,"channel");
HPM->share(clif,"clif");
HPM->share(chrif,"chrif");
HPM->share(guild,"guild");
@@ -5634,6 +5633,7 @@ void map_load_defaults(void) {
battle_defaults();
battleground_defaults();
buyingstore_defaults();
+ channel_defaults();
clif_defaults();
chrif_defaults();
guild_defaults();
@@ -5940,6 +5940,7 @@ int do_init(int argc, char *argv[])
atcommand->init(minimal);
battle->init(minimal);
instance->init(minimal);
+ channel->init(minimal);
chrif->init(minimal);
clif->init(minimal);
ircbot->init(minimal);
diff --git a/src/map/map.h b/src/map/map.h
index c28a65f52..9fca3e606 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -19,7 +19,7 @@
struct mob_data;
struct npc_data;
-struct hChSysCh;
+struct channel_data;
enum E_MAPSERVER_ST {
MAPSERVER_ST_RUNNING = CORE_ST_LAST,
@@ -694,7 +694,7 @@ struct map_data {
struct map_zone_data *prev_zone;
/* Hercules Local Chat */
- struct hChSysCh *channel;
+ struct channel_data *channel;
/* invincible_time_inc mapflag */
unsigned int invincible_time_inc;
diff --git a/src/map/pc.c b/src/map/pc.c
index 806bfb42c..2013bb652 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -15,6 +15,7 @@
#include "atcommand.h" // get_atcommand_level()
#include "battle.h" // battle_config
#include "battleground.h"
+#include "channel.h"
#include "chat.h"
#include "chrif.h"
#include "clif.h"
@@ -5042,8 +5043,8 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int
vending->close(sd);
}
- if (clif->hChSys->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) {
- clif->chsys_left(map->list[sd->bl.m].channel,sd);
+ if (map->list[sd->bl.m].channel) {
+ channel->leave(map->list[sd->bl.m].channel,sd);
}
}
diff --git a/src/map/pc.h b/src/map/pc.h
index 1785bd4c4..f6b6329b4 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -491,10 +491,9 @@ struct map_session_data {
int shadowform_id;
/* [Ind/Hercules] */
- struct hChSysCh **channels;
+ struct channel_data **channels;
unsigned char channel_count;
- struct hChSysCh *gcbind;
- bool stealth;
+ struct channel_data *gcbind;
unsigned char fontcolor;
unsigned int fontcolor_tid;
int64 hchsysch_tick;
diff --git a/src/map/script.c b/src/map/script.c
index a2ea86ac6..f50e56d2d 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -16,6 +16,7 @@
#include "atcommand.h"
#include "battle.h"
#include "battleground.h"
+#include "channel.h"
#include "chat.h"
#include "chrif.h"
#include "clif.h"
@@ -19012,6 +19013,29 @@ BUILDIN(shopcount) {
return true;
}
+/**
+ * @call channelmes("#channel", "message");
+ *
+ * Sends a message through the specified chat channel.
+ *
+ */
+BUILDIN(channelmes)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+ const char *channelname = script_getstr(st, 2);
+ struct channel_data *chan = channel->search(channelname, sd);
+
+ if (!chan) {
+ script_pushint(st, 0);
+ return true;
+ }
+
+ channel->send(chan, NULL, script_getstr(st, 3));
+
+ script_pushint(st, 1);
+ return true;
+}
+
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
BUILDIN(defpattern);
@@ -19637,6 +19661,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(tradertype,"i"),
BUILDIN_DEF(purchaseok,""),
BUILDIN_DEF(shopcount, "i"),
+
+ BUILDIN_DEF(channelmes, "ss"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up