// NOTE: Channel-T Packets are currently unsupported void channel_m(mixed *packet); mapping all_channels() { return config -> channel_list -> list; } mapping admin_channels() { return admin_channels; } string *listen_channels() { return listen_channels; } string *admitted_channels(string channel) { if (classp(admin_channels[channel])) return admin_channels[channel] -> members; return 0; } /* admitted_channels() */ string *available_channels() { return filter(keys(config -> channel_list -> list), (: member_array($1, listen_channels) != -1 :) ); } /* available_channels() */ int available_channel(string channel) { return (member_array(channel, available_channels()) != -1); } /* available_channel() */ int channel_exists(string channel) { return !undefinedp(config -> channel_list -> list[channel]); } /* channel_exists() */ int query_channel_type(string channel) { mixed *info; if (info = config -> channel_list -> list[channel]) return info[1]; } /* query_channel_type() */ string query_channel_owner(string channel) { mixed *info; if (info = config -> channel_list -> list[channel]) return info[0]; } /* query_channel_owner() */ void set_message_func(function f) { // if( file_name(PO) != USER_H ) return; channel_event_receiver = f; } /* set_event_receiver() */ // Send a channel message to the router int channel(string channel, string name, string message) { mixed *packet; if (message[0] == '@') { packet = packet_allocate(CHANNEL_E_PACKET); packet[P_SENDER] = lower_case(name); packet[S_P + CHANNEL_E_CNAME] = channel; packet[S_P + CHANNEL_E_VISNAME] = CAP(name); packet[S_P + CHANNEL_E_MESSAGE] = "$N " + message[1..]; } else { packet = packet_allocate(CHANNEL_M_PACKET); packet[P_SENDER] = lower_case(name); packet[S_P + CHANNEL_M_CNAME] = channel; packet[S_P + CHANNEL_M_VISNAME] = CAP(name); packet[S_P + CHANNEL_M_MESSAGE] = message; } add_buffer(0, packet); send_buffer(0); return 1; } /* channel() */ // Incoming remote emotes private void channel_e(mixed *packet) { string channel; string str; string who; if (sizeof(packet) != (S_P + SIZEOF_CHANNEL_E)) { packet_invalid(packet); return; } if (!available_channel(channel = packet[S_P + CHANNEL_E_CNAME])) return; if (!(channel = CHANNEL_H -> query_channel_name(channel))) return; str = packet[S_P + CHANNEL_E_MESSAGE]; str = ((str[0..1] == "$N") ? str[3..] : str); who = sprintf("%s@%s", capitalize(packet[S_P + CHANNEL_E_VISNAME]), capitalize(packet[P_SOURCE])); CHANNEL_H -> send_intermud_chat(0, channel, "", replace_string(str,"$N", who), // packet[S_P + CHANNEL_E_MESSAGE], 1, 0, who, ); return; } /* channel_e() */ // Incoming remote messages private void channel_m(mixed *packet) { string channel; if (sizeof(packet) != (S_P + SIZEOF_CHANNEL_M)) { packet_invalid(packet); return; } if (!available_channel(channel = packet[S_P + CHANNEL_M_CNAME])) return; if (!(channel = CHANNEL_H -> query_channel_name(channel))) return; CHANNEL_H -> send_intermud_chat(0, channel, "", packet[S_P + CHANNEL_M_MESSAGE], 0 , 0, packet[S_P + CHANNEL_M_VISNAME] + "@" + packet[P_SOURCE]); return; } /* channel_m() */ private void channel_t(mixed /* *packet */ ) { return; } /* channel_t() */ string listen_channel(string cname, int state) { mixed *packet; if (state < 0 || state > 1) return "Invalid intermud channel state.\n"; if (!channel_exists(cname)) return "No channel by that name exists.\n"; packet = packet_allocate(CHANNEL_LISTEN_PACKET); packet[P_DESTINATION] = config -> routers[0][0]; packet[P_SENDER] = (TU) ? TU -> query_name() : "admin"; packet[S_P + CHANNEL_LISTEN_CNAME] = cname; packet[S_P + CHANNEL_LISTEN_STATE] = state; add_buffer(0, packet); send_buffer(0); log_file("intermud", sprintf("channel-listen %s %d (%s)\n", cname, state, packet[P_SENDER])); if (state) { if (member_array(cname, listen_channels) == -1) listen_channels += ({ cname }); // Bind new channels to the user handler // TP -> add_channel(cname + "-channel", ({ (: creatorp($1) || // file_name($1) == INTERMUD_H :) }) ); // USER_H -> add_listener(cname + "-channel", (: channel :) ); return "Connecting to " + cname + ".\n"; } listen_channels -= ({ cname }); // Unbind the channel form the user handler // USER_H -> remove_channel(cname + "-channel"); return "Disconnecting from " + cname + ".\n"; } /* listen_channel() */ string create_channel(string cname, int ctype) { mixed *packet; if (!PRIVILEGE_H->query_privilege("admin.intermud.channel")) return "Insufficient privilege to affect intermud channels.\n"; // 0 - selectively banned. // 1 - selectively admitted. // 2 - filtered (selectively admitted). if (ctype < 0 || ctype > 2) return "Invalid intermud channel type.\n"; if (channel_exists(cname)) return "An intermud channel of that name already exists.\n"; packet = packet_allocate(CHANNEL_ADD_PACKET); packet[P_DESTINATION] = config -> routers[0][0]; packet[P_SENDER] = TU -> query_name(); packet[S_P + CHANNEL_ADD_CNAME] = cname; packet[S_P + CHANNEL_ADD_TYPE] = ctype; admin_channels[cname] = new(class admin_channel, type : ctype, members : ({ }) ); add_buffer(0, packet); send_buffer(0); log_file("intermud", sprintf("channel-add %s %d (%s)\n", cname, ctype, packet[P_SENDER])); return "Creating intermud channel "+ cname +" (type "+ ctype +").\n"; } /* create_channel() */ string delete_channel(string cname) { mixed *packet; if (!PRIVILEGE_H->query_privilege("admin.intermud.channel")) return "Insufficient privilege to affect intermud channels.\n"; if (!channel_exists(cname)) return "No intermud channel of that name exists.\n"; packet = packet_allocate(CHANNEL_REMOVE_PACKET); packet[P_DESTINATION] = config -> routers[0][0]; packet[P_SENDER] = TU -> query_name(); packet[S_P + CHANNEL_REMOVE_CNAME] = cname; map_delete(admin_channels, cname); add_buffer(0, packet); send_buffer(0); log_file("intermud", sprintf("channel-remove %s (%s)\n", cname, packet[P_SENDER])); return "Deleting intermud channel " + cname + ".\n"; } /* delete_channel() */ string administrate_channel(string cname, string *add_list, string *remove_list) { mixed *packet; string owner; if (base_name(PO) != INTERMUD_H) if (!PRIVILEGE_H->query_privilege("admin.intermud.channel")) return "Insufficient privilege to affect intermud channels.\n"; if (!channel_exists(cname)) return "No intermud channel of that name exists.\n"; if (MUD_NAME != (owner = query_channel_owner(cname))) return "Given channel not owned by this mud, but by "+ owner +".\n"; if (!arrayp(add_list)) add_list = ({ }); if (!arrayp(remove_list)) remove_list = ({ }); if (!sizeof(add_list) && !sizeof(remove_list)) return "Why bother making no changes (both lists are empty)?\n"; packet = packet_allocate(CHANNEL_ADMIN_PACKET); packet[P_DESTINATION] = config -> routers[0][0]; packet[P_SENDER] = objectp(TU) ? TU -> query_name() : "admin"; packet[S_P + CHANNEL_ADMIN_CNAME] = cname; packet[S_P + CHANNEL_ADMIN_ADD] = add_list; packet[S_P + CHANNEL_ADMIN_REMOVE] = remove_list; if (classp(admin_channels[cname])) { add_list = filter(add_list, (: member_array($1, $2) == -1 :), admin_channels[cname] -> members); admin_channels[cname] -> members += add_list; admin_channels[cname] -> members -= remove_list; } log_file("intermud", sprintf("channel-admin %s (%s)\n" "+ %s.\n" "- %s.\n", cname, packet[P_SENDER], query_multiple_short(add_list), query_multiple_short(remove_list))); add_buffer(0, packet); send_buffer(0); return "Administrating intermud channel " + cname + ".\n"; } /* administrate_channel() */ // Update available remote channels private void chanlist_reply(mixed *packet) { if (sizeof(packet) != (S_P + SIZEOF_CHANLIST_REPLY)) { packet_invalid(packet); return; } config -> channel_list -> id = packet[S_P + CHANLIST_REPLY_ID]; config -> channel_list -> list = filter(packet[S_P + CHANLIST_REPLY_LIST], (: stringp($1) && $2 :) ); // Register with the router the channels we're listening too. map(available_channels(), (: listen_channel($1, 1) :) ); if (sizeof(admin_channels)) map(keys(admin_channels), (: administrate_channel($1,$2,0) :), ns_libs); config -> configured = 1; save_me(); } /* chanlist_reply() */ private void chan_who_reply(mixed *packet) { string *users; object user; if (sizeof(packet) != (S_P + SIZEOF_CHAN_WHO_REPLY)) { packet_invalid(packet); return; } if (!(user = find_player(packet[P_RECIPIENT]))) return; users = packet[S_P + CHAN_WHO_REPLY_USERS]; if (sizeof(users)) { if ((users[0] == "Just ask.") || (!users[0]) || (users[0][0..23] == "There is no such channel")) return; } else { return; } tell_object(user, "" + packet[P_SOURCE] + ": " + implode(users, ", ") + "\n"); } /* chan_who_reply() */ private void chan_who_request(mixed *packet) { mixed *reply; string channel, *listeners; if (sizeof(packet) != (S_P + SIZEOF_CHAN_WHO_REQ)) { packet_invalid(packet); return; } if (!(channel = CHANNEL_H -> query_channel_name( packet[S_P + CHAN_WHO_REQ_CNAME]))) return; CHANNEL_H -> update_users(channel); if (!(listeners = CHANNEL_H -> query_users(channel))) listeners = ({ }); listeners = map(listeners, (: $1 -> query_cap_name() :) ); reply = packet_allocate(CHAN_WHO_REPLY_PACKET); reply[P_DESTINATION] = packet[P_SOURCE]; reply[P_RECIPIENT] = packet[P_SENDER]; reply[S_P + CHAN_WHO_REPLY_CNAME] = channel; reply[S_P + CHAN_WHO_REPLY_USERS] = listeners; add_buffer(0, reply); send_buffer(0); } /* chan_who_request() */ int chan_who(string channel, string mud) { mixed *packet; if (!mud) { map(config -> mud_list -> list, (: chan_who($(channel), $1) :) ); return 1; } if ((shutdown) || (!(mud = mud_exists(mud))) || (mud == MUD_NAME) || (!available_channel(channel))) return 0; // Service is unavailable packet = packet_allocate(CHAN_WHO_REQ_PACKET); packet[P_SENDER] = TU -> query_name(); packet[P_DESTINATION] = mud; packet[S_P + CHAN_WHO_REQ_CNAME] = channel; add_buffer(0, packet); send_buffer(0); return 1; } /* chan_who() */