/* EQ2Emulator: Everquest II Server Emulator Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net) This file is part of EQ2Emulator. EQ2Emulator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. EQ2Emulator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with EQ2Emulator. If not, see . */ #include "Chat.h" #include "../../common/Log.h" #include "../../common/ConfigReader.h" #include "../../common/PacketStruct.h" #include "../IRC/IRC.h" extern ConfigReader configReader; extern IRC irc; Chat::Chat() { m_channels.SetName("Chat::Channels"); } Chat::~Chat() { vector::iterator itr; m_channels.writelock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) safe_delete(*itr); m_channels.releasewritelock(__FUNCTION__, __LINE__); } void Chat::AddChannel(ChatChannel *channel) { m_channels.writelock(__FUNCTION__, __LINE__); channels.push_back(channel); m_channels.releasewritelock(__FUNCTION__, __LINE__); } unsigned int Chat::GetNumChannels() { unsigned int ret; m_channels.readlock(__FUNCTION__, __LINE__); ret = (unsigned int)channels.size(); m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; } EQ2Packet * Chat::GetWorldChannelList(Client *client) { PacketStruct *packet_struct = configReader.getStruct("WS_AvailWorldChannels", client->GetVersion()); Player *player = client->GetPlayer(); vector channels_to_send; vector::iterator itr; ChatChannel *channel; EQ2Packet *packet; int32 i = 0; bool add; if (packet_struct == NULL) { LogWrite(CHAT__ERROR, 0, "Chat", "Could not find packet 'WS_AvailWorldChannels' for client %s on version %i\n", player->GetName(), client->GetVersion()); return NULL; } m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { channel = *itr; if (channel->GetType() == CHAT_CHANNEL_TYPE_WORLD) { add = true; if (add && !channel->CanJoinChannelByLevel(player->GetLevel())) add = false; if (add && !channel->CanJoinChannelByRace(player->GetRace())) add = false; if (add && !channel->CanJoinChannelByClass(player->GetAdventureClass())) add = false; if (add) channels_to_send.push_back(channel); } } m_channels.releasereadlock(__FUNCTION__, __LINE__); packet_struct->setArrayLengthByName("num_channels", channels_to_send.size()); for (itr = channels_to_send.begin(); itr != channels_to_send.end(); itr++, i++) { packet_struct->setArrayDataByName("channel_name", (*itr)->GetName(), i); packet_struct->setArrayDataByName("unknown", 0, i); } packet = packet_struct->serialize(); safe_delete(packet_struct); return packet; } bool Chat::ChannelExists(const char *channel_name) { vector::iterator itr; bool ret = false; m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = true; break; } } m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; } bool Chat::HasPassword(const char *channel_name) { vector::iterator itr; bool ret = false; m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = (*itr)->HasPassword(); break; } } m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; } bool Chat::PasswordMatches(const char *channel_name, const char *password) { vector::iterator itr; bool ret = false; m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = (*itr)->PasswordMatches(password); break; } } m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; } bool Chat::CreateChannel(const char *channel_name) { return CreateChannel(channel_name, NULL); } bool Chat::CreateChannel(const char *channel_name, const char *password) { LogWrite(CHAT__DEBUG, 0, "Chat", "Channel %s being created", channel_name); ChatChannel *channel = new ChatChannel(); channel->SetName(channel_name); channel->SetType(CHAT_CHANNEL_TYPE_CUSTOM); if (password != NULL) channel->SetPassword(password); m_channels.writelock(__FUNCTION__, __LINE__); channels.push_back(channel); m_channels.releasewritelock(__FUNCTION__, __LINE__); return true; } bool Chat::IsInChannel(Client *client, const char *channel_name) { vector::iterator itr; bool ret = false; m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = (*itr)->IsInChannel(client->GetCharacterID()); break; } } m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; } bool Chat::JoinChannel(Client *client, const char *channel_name) { vector::iterator itr; bool ret = false; LogWrite(CHAT__DEBUG, 1, "Chat", "Client %s is joining channel %s", client->GetPlayer()->GetName(), channel_name); m_channels.writelock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = (*itr)->JoinChannel(client); break; } } m_channels.releasewritelock(__FUNCTION__, __LINE__); return ret; } bool Chat::LeaveChannel(Client *client, const char *channel_name) { vector::iterator itr; bool ret = false; LogWrite(CHAT__DEBUG, 1, "Chat", "Client %s is leaving channel %s", client->GetPlayer()->GetName(), channel_name); m_channels.writelock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = (*itr)->LeaveChannel(client); if ((*itr)->GetType() == CHAT_CHANNEL_TYPE_CUSTOM && (*itr)->GetNumClients() == 0) { LogWrite(CHAT__DEBUG, 0, "Chat", "Custom channel %s has 0 clients left, deleting channel", channel_name); safe_delete(*itr); channels.erase(itr); } break; } } m_channels.releasewritelock(__FUNCTION__, __LINE__); return ret; } bool Chat::LeaveAllChannels(Client *client) { vector::iterator itr; ChatChannel *channel; bool erased; m_channels.writelock(__FUNCTION__, __LINE__); itr = channels.begin(); while (itr != channels.end()) { channel = *itr; erased = false; if (channel->IsInChannel(client->GetCharacterID())) { LogWrite(CHAT__DEBUG, 1, "Chat", "Client %s is leaving channel %s", client->GetPlayer()->GetName(), channel->GetName()); channel->LeaveChannel(client); if (channel->GetType() == CHAT_CHANNEL_TYPE_CUSTOM && channel->GetNumClients() == 0) { LogWrite(CHAT__DEBUG, 0, "Chat", "Custom channel %s has 0 clients left, deleting channel", channel->GetName()); safe_delete(*itr); itr = channels.erase(itr); erased = true; } } if (!erased) itr++; } m_channels.releasewritelock(__FUNCTION__, __LINE__); return true; } bool Chat::TellChannel(Client *client, const char *channel_name, const char *message, const char* name) { vector::iterator itr; bool ret = false; m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { if (client && name) ret = (*itr)->TellChannelClient(client, message, name); else ret = (*itr)->TellChannel(client, message, name); // if client = null then it came from irc, don't send it back to irc if (client) { IRCServer* server = 0; bool global = false; string msg; const char* safe_name = irc.GetSafeChannelName(channel_name); // If global irc channel add "PlayerName says: " to the begining of the message if ((*itr)->IsGlobalIRCChannel()) { server = irc.GetGlobalServer(); msg = string(client->GetPlayer()->GetName()) + string(" says: ") + string(message); global = true; } else server = irc.GetServer(client); // if global channel don't send a client and send the modified message if (server && server->GetChannel(safe_name)) irc.Say(global ? 0 : client, channel_name, global ? msg.c_str() : message); } break; } } m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; } bool Chat::SendChannelUserList(Client *client, const char *channel_name) { vector::iterator itr; bool ret = false; m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = (*itr)->SendChannelUserList(client); break; } } m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; } ChatChannel* Chat::GetChannel(const char *channel_name) { vector::iterator itr; ChatChannel* ret = 0; m_channels.readlock(__FUNCTION__, __LINE__); for (itr = channels.begin(); itr != channels.end(); itr++) { if (strncasecmp(channel_name, (*itr)->GetName(), CHAT_CHANNEL_MAX_NAME) == 0) { ret = (*itr); break; } } m_channels.releasereadlock(__FUNCTION__, __LINE__); return ret; }