/** * Make a player leave a type of channel * @param sd: Player data * @param type: Quit type (1 - Quit guild channel, 2 - Quit ally channel, 4 - Quit map channel, 8 - Quit all users in channel) * @return * 0: Success * -1: Invalid player */ int channel_pcquit(struct map_session_data *sd, int type){ int i; //On closing state we could have clean all chan by sd but pcquit is more used to free unit when //he quit a map_server, not call in map_quit cause we need to cleanup when we switch map-server as well if(!sd) return -1; // Leave all chat channels. if(type&(1|2) && channel_config.ally_tmpl.name != NULL && sd->guild){ //quit guild and ally chan struct guild *g = sd->guild; if(type&1 && channel_haspc(g->channel,sd)==1){ channel_clean(g->channel,sd,0); //leave guild chan } if(type&2){ for (i = 0; i < MAX_GUILDALLIANCE; i++) { //leave all alliance chan struct guild *ag; //allied guild if( g->alliance[i].guild_id && (ag = guild_search(g->alliance[i].guild_id) ) ) { if(channel_haspc(ag->channel,sd) == 1) channel_clean(ag->channel,sd,0); break; } } } } if(type&4 && channel_config.map_tmpl.name != NULL && channel_haspc(map[sd->bl.m].channel,sd)==1){ //quit map chan channel_clean(map[sd->bl.m].channel,sd,0); } if(type&8 && sd->channel_count ) { //quit all chan uint8 count = sd->channel_count; for( i = count-1; i >= 0; i--) { //going backward to avoid shifting channel_clean(sd->channels[i],sd,0); } } return 0; }
/** * A player is attemting to kick a player * @param sd: Player data * @param chname: Channel name * @param pname: Player name to kick * @return 0 on success or -1 on failure */ int channel_pckick(struct map_session_data *sd, char *chname, char *pname) { struct Channel *channel; char output[CHAT_SIZE_MAX]; struct map_session_data *tsd = map_nick2sd(pname,false); if( channel_chk(chname,NULL,1) ) { clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'. return -1; } channel = channel_name2channel(chname,sd,0); if( !channel ) { sprintf(output, msg_txt(sd,1407), chname);// Channel '%s' is not available. clif_displaymessage(sd->fd, output); return -1; } if (!tsd) { clif_displaymessage(sd->fd, msg_txt(sd,3)); return -1; } if( !pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) { if (channel->char_id != sd->status.char_id) { sprintf(output, msg_txt(sd,1412), chname);// You're not the owner of channel '%s'. clif_displaymessage(sd->fd, output); } else if (!channel_config.private_channel.kick) { sprintf(output, msg_txt(sd,766), chname); // You cannot kick a player from channel '%s'. clif_displaymessage(sd->fd, output); } return -1; } if (channel_pc_haschan(sd, channel) < 0) { sprintf(output, msg_txt(sd,1425), chname); // You're not part of the '%s' channel. clif_displaymessage(sd->fd, output); return -1; } if (channel->char_id == sd->status.char_id) { clif_displaymessage(sd->fd, msg_txt(sd, 767)); // You're not allowed to kick a player. return -1; } if( !channel_config.closing && (channel->opt & CHAN_OPT_ANNOUNCE_LEAVE) ) { safesnprintf(output, CHAT_SIZE_MAX, msg_txt(sd,768), channel->alias, tsd->status.name); // %s %s has been kicked. clif_channel_msg(channel,output,channel->color); } switch(channel->type){ case CHAN_TYPE_ALLY: channel_pcquit(tsd,3); break; case CHAN_TYPE_MAP: channel_pcquit(tsd,4); break; default: //private and public atm channel_clean(channel,tsd,0); } return 1; }
/** * A player is attempting to leave a channel * @param sd: Player data * @param chname: Channel name * @return 0 on success or -1 on failure */ int channel_pcleave(struct map_session_data *sd, char *chname){ struct Channel *channel; char output[CHAT_SIZE_MAX]; if(!sd || !chname) return 0; if( channel_chk(chname,NULL,1) ) { clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'. return -1; } channel = channel_name2channel(chname,sd,0); if(channel_pc_haschan(sd,channel)<0){ sprintf(output, msg_txt(sd,1425),chname);// You're not part of the '%s' channel. clif_displaymessage(sd->fd, output); return -2; //channel doesn't exist or player don't have it } if (!(channel->opt&CHAN_OPT_CAN_LEAVE)) { sprintf(output, msg_txt(sd,762), chname); // You cannot leave channel '%s'. clif_displaymessage(sd->fd, output); return -1; } if( !channel_config.closing && (channel->opt & CHAN_OPT_ANNOUNCE_LEAVE) ) { safesnprintf(output, CHAT_SIZE_MAX, msg_txt(sd,763), channel->alias, sd->status.name); // %s %s left. clif_channel_msg(channel,output,channel->color); } switch(channel->type){ case CHAN_TYPE_ALLY: channel_pcquit(sd,3); break; case CHAN_TYPE_MAP: channel_pcquit(sd,4); break; default: //private and public atm channel_clean(channel,sd,0); } sprintf(output, msg_txt(sd,1426),chname); // You've left the '%s' channel. clif_displaymessage(sd->fd, output); return 0; }
/** * Delete a channel * - Checks if there is any user in channel and make them quit * @param channel: Channel data * @param force: Forcefully remove channel * @return * 0: Success * -1: Invalid channel * -2: Can't delete now */ int channel_delete(struct Channel *channel, bool force) { if(!channel) return -1; if(!force && channel->type == CHAN_TYPE_PUBLIC && runflag == MAPSERVER_ST_RUNNING) //only delete those serv stop return -2; if( db_size(channel->users)) { struct map_session_data *sd; DBIterator *iter = db_iterator(channel->users); for( sd = (struct map_session_data *)dbi_first(iter); dbi_exists(iter); sd = (struct map_session_data *)dbi_next(iter) ) { //for all users channel_clean(channel,sd,1); //make all quit } dbi_destroy(iter); } if (battle_config.etc_log) ShowInfo("Deleting channel %s alias %s type %d\n",channel->name,channel->alias,channel->type); db_destroy(channel->users); db_destroy(channel->banned); if (channel->groups) aFree(channel->groups); channel->groups = NULL; channel->group_count = 0; switch(channel->type){ case CHAN_TYPE_MAP: map_getmapdata(channel->m)->channel = NULL; aFree(channel); break; case CHAN_TYPE_ALLY: { struct guild *g = guild_search(channel->gid); if(g) g->channel = NULL; aFree(channel); break; } default: strdb_remove(channel_db, channel->name); break; } return 0; }
/** * A player is attempting to modify the banlist * @param sd: Player data * @param chname: Channel name * @param pname: Player to ban or unban * @param flag: Ban options (0 - Ban, 1 - Unban, 2 - Unban all, 3 - Ban list) * @return 0 on success or -1 on failure */ int channel_pcban(struct map_session_data *sd, char *chname, char *pname, int flag){ struct Channel *channel; char output[CHAT_SIZE_MAX]; struct map_session_data *tsd = map_nick2sd(pname,false); if( channel_chk(chname,NULL,1) ) { clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'. return -1; } channel = channel_name2channel(chname,sd,0); if( !channel ) { sprintf(output, msg_txt(sd,1407), chname);// Channel '%s' is not available. clif_displaymessage(sd->fd, output); return -1; } if( !pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) { if (channel->char_id != sd->status.char_id) { sprintf(output, msg_txt(sd,1412), chname);// You're not the owner of channel '%s'. clif_displaymessage(sd->fd, output); return -1; } else if (!channel_config.private_channel.ban) { sprintf(output, msg_txt(sd,765), chname); // You're not allowed to ban a player. clif_displaymessage(sd->fd, output); return -1; } } if(flag != 2 && flag != 3){ char banned; if(!tsd || pc_has_permission(tsd, PC_PERM_CHANNEL_ADMIN) ) { sprintf(output, msg_txt(sd,1464), pname);// Ban failed for player '%s'. clif_displaymessage(sd->fd, output); return -1; } banned = channel_haspcbanned(channel,tsd); if(!flag && banned==1) { sprintf(output, msg_txt(sd,1465), tsd->status.name);// Player '%s' is already banned from this channel. clif_displaymessage(sd->fd, output); return -1; } else if(flag==1 && banned==0) { sprintf(output, msg_txt(sd,1440), tsd->status.name);// Player '%s' is not banned from this channel. clif_displaymessage(sd->fd, output); return -1; } } else { if( !db_size(channel->banned) ) { sprintf(output, msg_txt(sd,1439), chname);// Channel '%s' contains no banned players. clif_displaymessage(sd->fd, output); return 0; } } //let properly alter the list now switch(flag){ case 0: { struct chan_banentry *cbe; if (!tsd) return -1; CREATE(cbe, struct chan_banentry, 1); cbe->char_id = tsd->status.char_id; strcpy(cbe->char_name,tsd->status.name); idb_put(channel->banned, tsd->status.char_id, cbe); channel_clean(channel,tsd,0); sprintf(output, msg_txt(sd,1437),tsd->status.name,chname); // Player '%s' is banned from the '%s' channel. break; } case 1: if (!tsd) return -1; idb_remove(channel->banned, tsd->status.char_id); sprintf(output, msg_txt(sd,1441),tsd->status.name,chname); // Player '%s' is unbanned from the '%s' channel. break; case 2: db_clear(channel->banned); sprintf(output, msg_txt(sd,1442),chname); // Cleared all bans from the '%s' channel. break; case 3: { DBIterator *iter = db_iterator(channel->banned); struct chan_banentry *cbe; sprintf(output, msg_txt(sd,1443), channel->name);// ---- '#%s' Ban List: clif_displaymessage(sd->fd, output); for( cbe = (struct chan_banentry *)dbi_first(iter); dbi_exists(iter); cbe = (struct chan_banentry *)dbi_next(iter) ) { //for all users if (cbe->char_name[0]) sprintf(output, "%d: %s",cbe->char_id,cbe->char_name); else sprintf(output, "%d: ****",cbe->char_id); clif_displaymessage(sd->fd, output); } dbi_destroy(iter); } return 0; } clif_displaymessage(sd->fd, output); return 0; }