/** * 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); nullpo_retr(HCS_STATUS_FAIL, password); 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_sd(sd,1435), chan->name, map->list[chan->m].name); // You're now in the '#%s' channel for '%s' } else { sprintf(output, msg_sd(sd,1403), chan->name); // You're now in the '%s' channel } clif->messagecolor_self(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)) != NULL) { 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; }
/** * 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; }
/** * 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; }
/** * Join an existing chat room. * @param sd : player requesting * @param chatid : ID of the chat room * @param pass : password of chat room * @return 0 */ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) { struct chat_data* cd; nullpo_ret(sd); cd = (struct chat_data*)map_id2bl(chatid); if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit ) { clif_joinchatfail(sd,0); return 0; } if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) { clif_joinchatfail(sd,1); return 0; } if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) { if(sd->status.base_level < cd->minLvl) clif_joinchatfail(sd,5); else clif_joinchatfail(sd,6); return 0; } if( sd->status.zeny < cd->zeny ) { clif_joinchatfail(sd,4); return 0; } if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) { clif_joinchatfail(sd,2);//You have been kicked out of the room. return 0; } pc_stop_walking(sd,1); cd->usersd[cd->users] = sd; cd->users++; pc_setchatid(sd,cd->bl.id); clif_joinchatok(sd, cd); //To the person who newly joined the list of all clif_addchat(cd, sd); //Reports To the person who already in the chat clif_dispchat(cd, 0); //Reported number of changes to the people around if (cd->owner->type == BL_PC) achievement_update_objective(map_id2sd(cd->owner->id), AG_CHAT_COUNT, 1, cd->users); chat_triggerevent(cd); //Event return 0; }
/*========================================== * join an existing chatroom *------------------------------------------*/ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) { struct chat_data* cd; nullpo_ret(sd); nullpo_ret(pass); cd = map->id2cd(chatid); if (cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chat_id != 0 || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit ) { clif->joinchatfail(sd,0); // room full return false; } if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) { clif->joinchatfail(sd,1); // wrong password return false; } if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) { if(sd->status.base_level < cd->minLvl) clif->joinchatfail(sd,5); // too low level else clif->joinchatfail(sd,6); // too high level return false; } if( sd->status.zeny < cd->zeny ) { clif->joinchatfail(sd,4); // not enough zeny return false; } if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) { clif->joinchatfail(sd,2); // You have been kicked out of the room. return false; } pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); cd->usersd[cd->users] = sd; cd->users++; pc_setchatid(sd,cd->bl.id); clif->joinchatok(sd, cd); //To the person who newly joined the list of all clif->addchat(cd, sd); //Reports To the person who already in the chat clif->dispchat(cd, 0); //Reported number of changes to the people around chat->trigger_event(cd); //Event return true; }
/** * Checks if player group with given ID exists. * @param group_id group id * @returns true if group exists, false otherwise */ bool pc_group_exists(int group_id) { return idb_exists(pc_group_db, group_id); }
/** * Check if player is banned from channel * @return * -1: Invalid player or channel * 0: Player not found or not banned * 1: Player is banned */ int channel_haspcbanned(struct Channel *channel,struct map_session_data *sd){ if(!channel || !sd) return -1; return (idb_exists(channel->banned, sd->status.char_id))?1:0; }