/** * A player is attempting to create a channel * @param sd: Player data * @param chname: Channel name * @param chpass: Channel password * @return 0 on success or -1 on failure */ int channel_pccreate(struct map_session_data *sd, char *chname, char *chpass){ char output[CHAT_SIZE_MAX]; int8 res; if(!sd || !chname) return 0; res = channel_chk(chname,chpass,7); if(res==0){ //success struct Channel *channel = channel_create_simple(chname,chpass,CHAN_TYPE_PRIVATE,sd->status.char_id); channel_join(channel,sd); if( ( channel->opt & CHAN_OPT_ANNOUNCE_SELF ) ) { sprintf(output, msg_txt(sd,1403),chname); // You're now in the '%s' channel. clif_displaymessage(sd->fd, output); } } else { //failure display cause switch(res){ case -1: sprintf(output, msg_txt(sd,1405), CHAN_NAME_LENGTH); break;// Channel name must start with '#'. case -2: sprintf(output, msg_txt(sd,1406), CHAN_NAME_LENGTH); break;// Channel length must be between 3 and %d. case -3: sprintf(output, msg_txt(sd,1436), CHAN_NAME_LENGTH); break;// Channel password can't be over %d characters. case -4: sprintf(output, msg_txt(sd,1407), chname);// Channel '%s' is not available. } clif_displaymessage(sd->fd, output); return -1; } 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 join a channel * @param sd: Player data * @param chname: Channel name * @param pass: Channel password * @return 0 on success or -1 on failure */ int channel_pcjoin(struct map_session_data *sd, char *chname, char *pass){ 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,1); if(channel){ if (!pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) && !channel_pccheckgroup(channel, sd->group_id)) { sprintf(output, msg_txt(sd,1407), chname); // Channel '%s' is not available. clif_displaymessage(sd->fd, output); return -1; } if(channel_haspc(channel,sd)==1) { sprintf(output, msg_txt(sd,1434),chname); // You're already in the '%s' channel. clif_displaymessage(sd->fd, output); return -1; } else if( channel->pass[0] != '\0') { //chan has a pass if(strcmp(channel->pass,pass) != 0){ //wrong pass entry if( pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) { sd->stealth = true; } else { sprintf(output, msg_txt(sd,1401),chname,"@join"); // Channel '%s' is password-protected (usage: %s <#channel_name> <password>). clif_displaymessage(sd->fd, output); return -1; } } } } else { sprintf(output, msg_txt(sd,1400),chname,"@join"); // Unknown channel '%s' (usage: %s <#channel_name>). clif_displaymessage(sd->fd, output); return -1; } switch(channel->type){ case CHAN_TYPE_ALLY: channel_gjoin(sd,3); break; case CHAN_TYPE_MAP: channel_mjoin(sd); break; default: //private and public atm if (channel_join(channel,sd) != 0) return -1; } if( ( channel->opt & CHAN_OPT_ANNOUNCE_SELF ) ) { sprintf(output, msg_txt(sd,1403),chname); // You're now in the '%s' channel. clif_displaymessage(sd->fd, output); } return 0; }
/** * A player is attempting to change the channel color * @param sd: Player data * @param chname: Channel name * @param color: New color * @return 0 on success or -1 on failure */ int channel_pccolor(struct map_session_data *sd, char *chname, char *color){ struct Channel *channel; char output[CHAT_SIZE_MAX]; int k; if(!sd) 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 ) { 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->opt&CHAN_OPT_COLOR_OVERRIDE)) { sprintf(output, msg_txt(sd,764), chname); // You cannot change the color for channel '%s'. clif_displaymessage(sd->fd, output); return -1; } } ARR_FIND(0,channel_config.colors_count,k,( strcmpi(color,channel_config.colors_name[k]) == 0 ) ); if( k >= channel_config.colors_count ) { sprintf(output, msg_txt(sd,1411), color);// Unknown color '%s'. clif_displaymessage(sd->fd, output); return -1; } channel->color = channel_config.colors[k]; sprintf(output, msg_txt(sd,1413),chname,channel_config.colors_name[k]);// '%s' channel color updated to '%s'. clif_displaymessage(sd->fd, output); return 0; }
/** * Lookup a channel name * @param chname: Channel name * @param sd: Player data, can be NULL, used to solve #map and #ally cases * @param flag: Lookup types (1 - Create channel if it does not exist (map or ally only), 2 - Join the channel if not joined yet (map or ally only)) * @return NULL on channel not found or channel data on success */ struct Channel* channel_name2channel(char *chname, struct map_session_data *sd, int flag){ if(channel_chk(chname, NULL, 1)) return NULL; if(sd && strcmpi(chname + 1,channel_config.map_tmpl.name) == 0){ if(flag&1 && !map[sd->bl.m].channel) map[sd->bl.m].channel = channel_create_simple(NULL,NULL,CHAN_TYPE_MAP,sd->bl.m); if(flag&2 && channel_pc_haschan(sd,map[sd->bl.m].channel) < 1) channel_mjoin(sd); return map[sd->bl.m].channel; } else if(sd && (strcmpi(chname + 1,channel_config.ally_tmpl.name) == 0) && sd->guild){ if(flag&1 && !sd->guild->channel) sd->guild->channel = channel_create_simple(NULL,NULL,CHAN_TYPE_ALLY,sd->guild->guild_id); if(flag&2 && channel_pc_haschan(sd,map[sd->bl.m].channel) < 1) channel_gjoin(sd,3); return sd->guild->channel; } else return (struct Channel*) strdb_get(channel_db, chname + 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; }
/** * A player is attempting to bind * - Makes default message output display to the channel * @param sd: Player data * @param chname: Channel name * @return 0 on success, -1 on incorrect channel name, or -2 channel doesn't exist or player didn't join */ int channel_pcbind(struct map_session_data *sd, char *chname){ struct Channel *channel; char output[CHAT_SIZE_MAX]; if(!sd) 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 } sd->gcbind = channel; sprintf(output, msg_txt(sd,1431),chname); // Your global chat is now binded to the '%s' channel. clif_displaymessage(sd->fd, output); return 0; }
/** * A player is attempting to delete a channel * @param sd: Player data * @param chname: Channel name * @return 0 on success or -1 on failure */ int channel_pcdelete(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 } channel_delete(channel,false); sprintf(output, msg_txt(sd,1448),chname); // Channel '%s' deleted. clif_displaymessage(sd->fd, output); 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; }
/** * A player is attempting to set an option on the channel * @param sd: Player data * @param chname: Channel name * @param option: Option to change * @param val: Option value * @return 0 on success or -1 on failure */ int channel_pcsetopt(struct map_session_data *sd, char *chname, const char *option, const char *val){ struct Channel *channel; char output[CHAT_SIZE_MAX]; int k, s = 0, opt; const char* opt_str[] = { "None", "SelfAnnounce", "JoinAnnounce", "LeaveAnnounce", "MessageDelay", "ColorOverride", "CanChat", "CanLeave", "Autojoin", }; if( channel_chk(chname,NULL,1) ) { clif_displaymessage(sd->fd, msg_txt(sd,1405));// Channel name must start with '#'. return -1; } if (!sd) 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( sd && channel->char_id != sd->status.char_id && !pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) { sprintf(output, msg_txt(sd,1412), chname);// You're not the owner of channel '%s'. clif_displaymessage(sd->fd, output); return -1; } s = ARRAYLENGTH(opt_str); ARR_FIND(1,s,k,( strncmpi(option,opt_str[k],3) == 0 )); //we only cmp 3 letter atm if(!option || option[0] == '\0' || k >= s ) { sprintf(output, msg_txt(sd,1447), option);// Unknown channel option '%s'. clif_displaymessage(sd->fd, output); clif_displaymessage(sd->fd, msg_txt(sd,1414));// ---- Available options: for( k = 1; k < s; k++ ) { sprintf(output, msg_txt(sd,1445), opt_str[k]);// - '%s' clif_displaymessage(sd->fd, output); } return -1; } opt = 1<<(k-1); if (channel->type == CHAN_TYPE_PRIVATE && !pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN)) { switch (opt) { case CHAN_OPT_MSG_DELAY: if (!channel_config.private_channel.change_delay) return -1; break; case CHAN_OPT_COLOR_OVERRIDE: if (!channel_config.private_channel.color_override) return -1; break; } } if( val[0] == '\0' ) { if ( opt == CHAN_OPT_MSG_DELAY ) { sprintf(output, msg_txt(sd,1466), opt_str[k]);// Input the number of seconds (0-10) for the '%s' option. clif_displaymessage(sd->fd, output); return -1; } else if( channel->opt & opt ) { sprintf(output, msg_txt(sd,1449), opt_str[k],opt_str[k]); // Option '%s' is already enabled (use '@channel setopt %s 0' to disable). clif_displaymessage(sd->fd, output); return -1; } else { channel->opt |= opt; sprintf(output, msg_txt(sd,1450), opt_str[k],channel->name);// Option '%s' is enabled for channel '#%s'. clif_displaymessage(sd->fd, output); } } else { int v = atoi(val); if( opt == CHAN_OPT_MSG_DELAY ) { if( v < 0 || v > 10 ) { sprintf(output, msg_txt(sd,1451), v, opt_str[k]);// Value '%d' for option '%s' is out of range (limit 0-10). clif_displaymessage(sd->fd, output); return -1; } if( v == 0 ) { channel->opt &=~ opt; channel->msg_delay = 0; sprintf(output, msg_txt(sd,1453), opt_str[k],channel->name,v);// Option '%s' is disabled for channel '#%s'. clif_displaymessage(sd->fd, output); } else { channel->opt |= opt; channel->msg_delay = v * 1000; sprintf(output, msg_txt(sd,1452), opt_str[k],channel->name,v);// Option '%s' is enabled for channel '#%s' at %d seconds. clif_displaymessage(sd->fd, output); } } else { if( v ) { if( channel->opt & opt ) { sprintf(output, msg_txt(sd,1449), opt_str[k],opt_str[k]); // Option '%s' is already enabled (use '@channel setopt %s 0' to disable). clif_displaymessage(sd->fd, output); return -1; } else { channel->opt |= opt; sprintf(output, msg_txt(sd,1450), opt_str[k],channel->name);// Option '%s' is enabled for channel '#%s'. clif_displaymessage(sd->fd, output); } } else { if( !(channel->opt & opt) ) { sprintf(output, msg_txt(sd,1450), opt_str[k],channel->name); // Option '%s' is enabled for channel '#%s'. clif_displaymessage(sd->fd, output); return -1; } else { channel->opt &=~ opt; sprintf(output, msg_txt(sd,1453), opt_str[k],channel->name);// Option '%s' is disabled for channel '#%s'. clif_displaymessage(sd->fd, output); } } } } return 0; }