summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/atcommand.c57
-rw-r--r--src/map/channel.c86
-rw-r--r--src/map/channel.h6
-rw-r--r--src/map/clif.c15
-rw-r--r--src/map/guild.c18
-rw-r--r--src/map/pc.h1
6 files changed, 107 insertions, 76 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index bf99d4c20..0f33a387c 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -8612,9 +8612,11 @@ ACMD(cart) {
#undef MC_CART_MDFY
}
/* [Ind/Hercules] */
-ACMD(join) {
+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>)
@@ -8632,56 +8634,35 @@ ACMD(join) {
struct guild *g = sd->guild;
if( !g ) return false;/* unlikely, but we wont let it crash anyway. */
chan = g->channel;
- } else if( !( chan = strdb_get(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;
+ } else {
+ chan = strdb_get(channel->db, name + 1);
}
- if( !chan ) {
+ 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(chan->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( chan->password[0] != '\0' && strcmp(chan->password,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( chan->banned && idb_exists(chan->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 (!(chan->options & HCS_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( 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(sg->channel,sd);
- }
- }
- }
- }
- channel->join(chan,sd);
return true;
}
@@ -8750,6 +8731,7 @@ ACMD(channel) {
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;
@@ -8768,15 +8750,10 @@ ACMD(channel) {
}
chan = channel->create(HCS_TYPE_PRIVATE, sub1 + 1, 0);
- channel->set_password(chan, sub2);
+ channel->set_password(chan, pass);
chan->owner = sd->status.char_id;
- if( !( chan->options & HCS_OPT_ANNOUNCE_JOIN ) ) {
- sprintf(atcmd_output, msg_txt(1403),sub1); // You're now in the '%s' channel
- clif->message(fd, atcmd_output);
- }
-
- channel->join(chan,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) {
diff --git a/src/map/channel.c b/src/map/channel.c
index b0640eeff..49f5c9daa 100644
--- a/src/map/channel.c
+++ b/src/map/channel.c
@@ -196,17 +196,25 @@ void channel_send(struct channel_data *chan, struct map_session_data *sd, const
}
}
-void channel_join(struct channel_data *chan, struct map_session_data *sd)
+/**
+ * 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 (sd->stealth) {
- sd->stealth = false;
- } else if (chan->options & HCS_OPT_ANNOUNCE_JOIN) {
+ 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);
@@ -219,6 +227,69 @@ void channel_join(struct channel_data *chan, struct map_session_data *sd)
}
+/**
+ * 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];
+ sprintf(output, msg_txt(1403), chan->name); // You're now in the '%s' channel
+ clif->message(sd->fd, 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;
+}
+
void channel_map_join(struct map_session_data *sd)
{
if (sd->state.autotrade || sd->state.standalone)
@@ -235,7 +306,7 @@ void channel_map_join(struct map_session_data *sd)
return;
}
- channel->join(map->list[sd->bl.m].channel,sd);
+ channel->join_sub(map->list[sd->bl.m].channel,sd, false);
if (!( map->list[sd->bl.m].channel->options & HCS_OPT_ANNOUNCE_JOIN )) {
char mout[60];
@@ -414,7 +485,7 @@ void channel_guild_join(struct guild *g1,struct guild *g2)
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)))
- channel->join(chan,sd);
+ channel->join_sub(chan,sd, false);
}
}
}
@@ -423,7 +494,7 @@ void channel_guild_join(struct guild *g1,struct guild *g2)
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)))
- channel->join(chan,sd);
+ channel->join_sub(chan,sd, false);
}
}
}
@@ -712,6 +783,7 @@ void channel_defaults(void)
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->delete = channel_delete;
diff --git a/src/map/channel.h b/src/map/channel.h
index 11ba968a9..8709a9f96 100644
--- a/src/map/channel.h
+++ b/src/map/channel.h
@@ -40,6 +40,7 @@ enum channel_operation_status {
HCS_STATUS_FAIL,
HCS_STATUS_ALREADY,
HCS_STATUS_NOPERM,
+ HCS_STATUS_BANNED,
};
/**
@@ -85,6 +86,7 @@ struct channel_interface {
int (*init) (bool minimal);
void (*final) (void);
+ struct channel_data *(*search) (const char *name);
struct channel_data *(*create) (enum channel_types type, const char *name, unsigned char color);
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);
@@ -92,7 +94,9 @@ struct channel_interface {
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) (struct channel_data *chan, struct map_session_data *sd);
+ 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 (*delete) (struct channel_data *chan);
void (*map_join) (struct map_session_data *sd);
diff --git a/src/map/clif.c b/src/map/clif.c
index 10ab7121a..c66176d45 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -10062,20 +10062,9 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
if( sd->channels[k] == chan )
break;
}
- if( k < sd->channel_count ) {
+ if (k < sd->channel_count) {
channel->send(chan,sd,message);
- } else if( chan->password[0] == '\0' && !(chan->banned && idb_exists(chan->banned, sd->status.account_id)) ) {
- if( chan->type == HCS_TYPE_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)))
- channel->join(sg->channel,sd);
- }
- }
- }
- channel->join(chan,sd);
+ } else if (channel->join(chan, sd, NULL, true) == HCS_STATUS_OK) {
channel->send(chan,sd,message);
} else {
clif->message(fd, msg_txt(1402));
diff --git a/src/map/guild.c b/src/map/guild.c
index 3e71e99dc..a33efb831 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -489,13 +489,13 @@ int guild_recv_info(struct guild *sg) {
if (sd->status.guild_id == sg->guild_id) {
// Guild member
- channel->join(chan,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)))
- channel->join(tg[i]->channel, sd);
+ channel->join_sub(tg[i]->channel, sd, false);
}
continue;
}
@@ -504,7 +504,7 @@ int guild_recv_info(struct guild *sg) {
if (tg[i] && sd->status.guild_id == tg[i]->guild_id) { // Shortcut to skip the alliance checks again
// Alliance member
if( !(chan->banned && idb_exists(chan->banned, sd->status.account_id)))
- channel->join(chan, sd);
+ channel->join_sub(chan, sd, false);
}
}
}
@@ -741,17 +741,7 @@ void guild_member_joined(struct map_session_data *sd)
sd->guild = g;
if (channel->config->ally && channel->config->ally_autojoin) {
- struct channel_data *chan = g->channel;
-
- if( !(chan->banned && idb_exists(chan->banned, sd->status.account_id) ) )
- channel->join(chan,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)))
- channel->join(sg->channel,sd);
- }
- }
+ channel->join(g->channel, sd, NULL, true);
}
}
diff --git a/src/map/pc.h b/src/map/pc.h
index 167aa6010..f6b6329b4 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -494,7 +494,6 @@ struct map_session_data {
struct channel_data **channels;
unsigned char channel_count;
struct channel_data *gcbind;
- bool stealth;
unsigned char fontcolor;
unsigned int fontcolor_tid;
int64 hchsysch_tick;