Exemple #1
0
void CChat::FormatName(CGString &sName, const CChatMember *pMember, bool bSystem)	//static
{
	ADDTOCALLSTACK("CChat::FormatName");
	// Format chat name with proper color
	// 0 = Yellow (user)
	// 1 = Purple (moderator)
	// 2 = Blue (muted)
	// 3 = Purple (unused?)
	// 4 = White (me)
	// 5 = Green (system)

	int iColor = 0;
	if ( pMember )
	{
		CChatChannel *pChannel = pMember->GetChannel();
		if ( pChannel )
		{
			LPCTSTR pszName = const_cast<CChatMember *>(pMember)->GetChatName();
			if ( pChannel->IsModerator(pszName) )
				iColor = 1;
			else if ( !pChannel->HasVoice(pszName) )
				iColor = 2;

			sName.Format("%d%s", iColor, pszName);
			return;
		}
	}

	iColor = bSystem ? 5 : 4;
	sName.Format("%d%s", iColor, "SYSTEM");
}
void CChat::DecorateName(CGString &sName, const CChatChanMember * pMember, bool fSystem) // static
{
	ADDTOCALLSTACK("CChat::DecorateName");
	CChatChannel * pChannel = NULL;
	if (pMember)
		pChannel = pMember->GetChannel();
	// 0 = yellow
	// 1 = purple
	// 2 = blue
	// 3 = purple
	// 4 = white
	// 5 = green
	int iResult = 0;
	if (!pMember || !pChannel) // Must be a system command if these are invalid
	{
		if (fSystem)
			iResult = 5;
		else
			iResult = 4;
	}
	else if (pChannel->IsModerator(pMember->GetChatName()))
		iResult = 1;
	else if (!pChannel->HasVoice(pMember->GetChatName()))
		iResult = 2;

	if (!pMember || !pChannel)
		sName.Format("%i%s", iResult, "SYSTEM");
	else
		sName.Format("%i%s", iResult, static_cast<LPCTSTR>(pMember->GetChatName()));
}
Exemple #3
0
bool CChat::CreateChannel(LPCTSTR pszName, LPCTSTR pszPassword, CChatMember *pMember)
{
	ADDTOCALLSTACK("CChat::CreateChannel");
	if ( pMember )
	{
		CClient *pClient = pMember->GetClient();
		if ( pClient && !pClient->IsPriv(PRIV_GM) && !(g_Cfg.m_iChatFlags & CHATF_CHANNELCREATION) )
		{
			CGString sName;
			FormatName(sName, NULL, true);
			pMember->SendChatMsg(CHATMSG_PlayerMessage, sName, " Channel creation is disabled.");
			return false;
		}
	}
	if ( !IsValidName(pszName, false) )
	{
		if ( pMember )
			pMember->SendChatMsg(CHATMSG_InvalidConferenceName);
		return false;
	}
	else if ( FindChannel(pszName) )
	{
		if ( pMember )
			pMember->SendChatMsg(CHATMSG_DuplicatedConferenceName);
		return false;
	}

	CChatChannel *pChannel = new CChatChannel(pszName, pszPassword, !pMember);
	m_Channels.InsertTail(pChannel);
	BroadcastAddChannel(pChannel);
	if ( pMember && (g_Cfg.m_iChatFlags & CHATF_CHANNELMODERATION) )
		pChannel->SetModerator(pMember->GetChatName());
	return true;
}
void CChat::KillChannels()
{
	ADDTOCALLSTACK("CChat::KillChannels");
	CChatChannel * pChannel = GetFirstChannel();
	// First /kick everyone
	for ( ; pChannel != NULL; pChannel = pChannel->GetNext())
		pChannel->KickAll();
	m_Channels.Empty();
}
Exemple #5
0
void CChat::QuitChat(CChatMember *pClient)
{
	ADDTOCALLSTACK("CChat::QuitChat");
	// Remove from old channel (if any)

	CChatChannel *pCurrentChannel = pClient->GetChannel();
	if ( pCurrentChannel )
		pCurrentChannel->RemoveMember(pClient);
}
Exemple #6
0
CChatChannel * CChat::FindChannel(lpctstr pszChannel) const
{
	CChatChannel * pChannel = GetFirstChannel();
	for ( ; pChannel != nullptr; pChannel = pChannel->GetNext())
	{
		if (strcmp(pChannel->GetName(), pszChannel) == 0)
			break;
	}
	return pChannel;
}
void CChatChanMember::RenameChannel(LPCTSTR pszName)
{
	ADDTOCALLSTACK("CChatChanMember::RenameChannel");
	CChatChannel * pChannel = GetChannel();
	if (!pChannel)
		SendChatMsg(CHATMSG_MustBeInAConference);
	else if (!pChannel->IsModerator(pszName))
		SendChatMsg(CHATMSG_MustHaveOps);
	else
		pChannel->RenameChannel(this, pszName);
}
bool CChat::CreateChannel(LPCTSTR pszName, LPCTSTR pszPassword, CChatChanMember * pMember)
{
	ADDTOCALLSTACK("CChat::CreateChannel");
	if (!m_fChatsOK)
	{
		CGString sName;
		DecorateName(sName, NULL, true);
		pMember->SendChatMsg(CHATMSG_PlayerTalk, sName, "Conference creation is disabled.");
		return false;
	}
	CChatChannel * pChannel = new CChatChannel( pszName, pszPassword );
	m_Channels.InsertTail( pChannel );
	pChannel->SetModerator(pMember->GetChatName());
	// Send all clients with an open chat window the new channel name
	SendNewChannel(pChannel);
	return true;
}
Exemple #9
0
CChatChannel *CChat::FindChannel(LPCTSTR pszChannel) const
{
	ADDTOCALLSTACK("CChat::FindChannel");
	for ( CChatChannel *pChannel = static_cast<CChatChannel *>(m_Channels.GetHead()); pChannel != NULL; pChannel = pChannel->GetNext() )
	{
		if ( strcmpi(static_cast<LPCTSTR>(pChannel->m_sName), pszChannel) == 0 )
			return pChannel;
	}
	return NULL;
};
Exemple #10
0
void CChat::QuitChat(CChatChanMember * pClient)
{
	ADDTOCALLSTACK("CChat::QuitChat");
	// Are we in a channel now?
	CChatChannel * pCurrentChannel = pClient->GetChannel();
	// Remove from old channel (if any)
	if (pCurrentChannel)
	{
		// Remove myself from the channels list of members
		pCurrentChannel->RemoveMember( pClient );

		// Am I the last one here? Delete it from all other clients?
		if (pCurrentChannel->m_Members.GetCount() <= 0)
		{
			// If noone is left, tell the chat system to delete it from memory
			DeleteChannel(pCurrentChannel);
		}
	}
	// Now tell the chat system you left

	pClient->SetChatInactive();
}
Exemple #11
0
void CChat::JoinChannel(LPCTSTR pszName, LPCTSTR pszPassword, CChatMember *pMember)
{
	ADDTOCALLSTACK("CChat::JoinChannel");
	ASSERT(pMember);
	CClient *pMemberClient = pMember->GetClient();
	ASSERT(pMemberClient);

	CChatChannel *pNewChannel = FindChannel(pszName);
	if ( !pNewChannel )
	{
		pMemberClient->addChatSystemMessage(CHATMSG_NoConference, pszName);
		return;
	}
	pszName = pNewChannel->m_sName;	// fix case-sensitive mismatch

	CChatChannel *pCurrentChannel = pMember->GetChannel();
	if ( pCurrentChannel && (pCurrentChannel == pNewChannel) )
	{
		pMember->SendChatMsg(CHATMSG_AlreadyInConference, pszName);
		return;
	}
	else if ( !pNewChannel->m_sPassword.IsEmpty() && (!pszPassword || (strcmp(static_cast<LPCTSTR>(pNewChannel->m_sPassword), pszPassword) != 0)) )
	{
		if ( pMemberClient->m_UseNewChatSystem )
		{
			CGString sName;
			FormatName(sName, NULL, true);
			pMember->SendChatMsg(CHATMSG_PlayerMessage, sName, " Your client version can't join channels with password.");
		}
		else
			pMemberClient->addChatSystemMessage(CHATMSG_IncorrectPassword);
		return;
	}
	/*else if ( pNewChannel->m_Members.GetCount() >= UCHAR_MAX )
	{
		pMemberClient->addChatSystemMessage(CHATMSG_ConferenceIsFull, pszName);
		return;
	}*/

	// Leave current channel
	if ( pCurrentChannel )
		pCurrentChannel->RemoveMember(pMember);

	// Join the new channel
	pNewChannel->AddMember(pMember);
	pNewChannel->SendMember(pMember);		// send this member to all others clients
	pMemberClient->addChatSystemMessage(CHATCMD_JoinedChannel, pszName);
	if ( !pMemberClient->m_UseNewChatSystem )
		pNewChannel->FillMembersList(pMember);	// fill the members list on this client
}
Exemple #12
0
void CChatMember::addChatWindow()
{
	ADDTOCALLSTACK("CChatMember::addChatWindow");
	// Called from Event_ChatButton

	CClient *pClient = GetClient();
	if ( !pClient || (!pClient->m_UseNewChatSystem && m_bChatActive) )
		return;

	// Open chat window (old chat system only)
	// On new chat system this is not needed because the chat button is hardcoded on client-side, and
	// PacketChatButton packet is sent by client after login complete only to get initial channel list
	if ( !pClient->m_UseNewChatSystem )
		pClient->addChatSystemMessage(CHATCMD_OpenChatWindow, GetChatName());

	// Send channel names
	for ( CChatChannel *pChannel = static_cast<CChatChannel *>(g_Serv.m_Chats.m_Channels.GetHead()); pChannel != NULL; pChannel = pChannel->GetNext() )
	{
		pClient->addChatSystemMessage(CHATCMD_AddChannel, pChannel->m_sName, pClient->m_UseNewChatSystem ? NULL : pChannel->GetPasswordString());
		if ( (g_Cfg.m_iChatFlags & CHATF_AUTOJOIN) && pChannel->m_bStatic && !GetChannel() )
			g_Serv.m_Chats.JoinChannel(pChannel->m_sName, NULL, this);
	}
}
Exemple #13
0
void CChat::EventMsg( CClient * pClient, const NCHAR * pszText, int len, CLanguageID lang ) // Text from a client
{
	ADDTOCALLSTACK("CChat::EventMsg");
	// ARGS:
	//  len = length of the pszText string in NCHAR's.
	//

	CChatChanMember * pMe = pClient;
	ASSERT(pMe);

	// newer clients do not send the 'chat button' packet, leading to all kinds of problems
	// with the client not being initialised properly for chat (e.g. blank name and exceptions
	// when leaving a chat room) - if chat is not active then we must simulate the chat button
	// event before processing the chat message
	if (pMe->IsChatActive() == false)
	{
		// simulate the chat button being clicked
		pClient->Event_ChatButton(NULL);

		// if chat isn't active now then cancel processing the event
		if (pMe->IsChatActive() == false)
			return;
	}

	CChatChannel * pChannel =  pMe->GetChannel();

	TCHAR szText[MAX_TALK_BUFFER * 2];
	CvtNUNICODEToSystem( szText, sizeof(szText), pszText, len );

	// The 1st character is a command byte, join channel, private message someone, etc etc
	TCHAR * szMsg = szText+1;
	switch ( szText[0] )
	{
	case 'a':	// a = client typed a plain message in the text entry area
	{
		// Check for a chat command here
		if (szMsg[0] == '/')
		{
			DoCommand(pMe, szMsg + 1);
			break;
		}
		if (!pChannel)
		{
not_in_a_channel:
			pMe->SendChatMsg(CHATMSG_MustBeInAConference);
			return;
		}
		// Not a chat command, must be speech
		pChannel->MemberTalk(pMe, szMsg, lang);
		break;
	};
	case 'A':	// A = change the channel password
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->ChangePassword(pMe, szMsg);
		break;
	};
	case 'b':	// b = client joining an existing channel
	{
		// Look for second double quote to separate channel from password
		size_t i = 1;
		for (; szMsg[i] != '\0'; i++)
			if (szMsg[i] == '"')
				break;
		szMsg[i] = '\0';
		TCHAR * pszPassword = szMsg + i + 1;
		if (pszPassword[0] == ' ') // skip leading space if any
			pszPassword++;
		JoinChannel( pMe, szMsg + 1, pszPassword);
		break;
	};
	case 'c':	// c = client creating (and joining) new channel
	{
		TCHAR * pszPassword = NULL;
		size_t iMsgLength = strlen(szMsg);
		for (size_t i = 0; i < iMsgLength; i++)
		{
			if (szMsg[i] == '{') // OK, there's a password here
			{
				szMsg[i] = 0;
				pszPassword = szMsg + i + 1;
				size_t iPasswordLength = strlen(pszPassword);
				for (i = 0; i < iPasswordLength; i++)
				{
					if (pszPassword[i] == '}')
					{
						pszPassword[i] = '\0';
						break;
					}
				}
				break;
			}
		}
		CreateJoinChannel(pMe, szMsg, pszPassword);
		break;
	};
	case 'd':	// d = (/rename x) rename conference
	{
		if (!pChannel)
			goto not_in_a_channel;
		pMe->RenameChannel(szMsg);
		break;
	};
	case 'e':	// e = Send a private message to ....
	{
		if (!pChannel)
			goto not_in_a_channel;
		TCHAR buffer[2048];
		strcpy(buffer, szMsg);
		// Separate the recipient from the message (look for a space)
		size_t i = 0;
		size_t bufferLength = strlen(buffer);
		for (; i < bufferLength; i++)
		{
			if (buffer[i] == ' ')
			{
				buffer[i] = '\0';
				break;
			}
		}
		pChannel->SendPrivateMessage(pMe, buffer, buffer+i+1);
		break;
	};
	case 'f':	// f = (+ignore) ignore this person
	{
		pMe->Ignore(szMsg);
		break;
	};
	case 'g':	// g = (-ignore) don't ignore this person
	{
		pMe->DontIgnore(szMsg);
		break;
	};
	case 'h':	// h = toggle ignoring this person
	{
		pMe->ToggleIgnore(szMsg);
		break;
	};
	case 'i':	// i = grant speaking privs to this person
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->GrantVoice(pMe, szMsg);
		break;
	};
	case 'j':	// j = remove speaking privs from this person
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->RevokeVoice(pMe, szMsg);
		break;
	};
	case 'k':	// k = (/voice) toggle voice status
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->ToggleVoice(pMe, szMsg);
		break;
	};
	case 'l':	// l = grant moderator status to this person
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->GrantModerator(pMe, szMsg);
		break;
	};
	case 'm':	// m = remove moderator status from this person
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->RevokeModerator(pMe, szMsg);
		break;
	};
	case 'n':	// m = toggle the moderator status for this person
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->ToggleModerator(pMe, szMsg);
		break;
	}
	case 'o':	// o = turn on receiving private messages
	{
		pMe->SetReceiving(true);
		break;
	}
	case 'p':	// p = turn off receiving private messages
	{
		pMe->SetReceiving(false);
		break;
	}
	case 'q':	// q = toggle receiving messages
	{
		pMe->ToggleReceiving();
		break;
	};
	case 'r':	// r = (+showname) turn on showing character name
	{
		pMe->PermitWhoIs();
		break;
	};
	case 's':	// s = (-showname) turn off showing character name
	{
		pMe->ForbidWhoIs();
		break;
	};
	case 't':	// t = toggle showing character name
	{
		pMe->ToggleWhoIs();
		break;
	};
	case 'u':	// u = who is this player
	{
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->WhoIs(pMe->GetChatName(), szMsg);
		break;
	};
	case 'v':	// v = kick this person out of the conference
	{
		if (!pChannel)
			goto not_in_a_channel;

		CChatChanMember * pMember = pChannel->FindMember(szMsg);
		if (!pMember)
		{
			pMe->SendChatMsg(CHATMSG_NoPlayer, szMsg);
			break;
		}

		pChannel->KickMember(pMe, pMember);
		// If noone is left, tell the chat system to
		// delete it from memory (you can kick yourself)
		if (pChannel->m_Members.GetCount() <= 0) // Kicked self
		{
			DeleteChannel(pChannel);
		}
		break;
	};
	case 'X':	// X = client quit chat
		QuitChat(pClient);
		break;
	case 'w':	// w = (+defaultvoice) make moderators be the only ones with a voice by default
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->DisableVoiceDefault(pMe->GetChatName());
		break;
	case 'x':	// x = (-defaultvoice) give everyone a voice by default
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->EnableVoiceDefault(pMe->GetChatName());
		break;
	case 'y':	// y = (/defaultvoice) toggle
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->ToggleVoiceDefault(pMe->GetChatName());
		break;
	case 'z':	// z = emote
		if (!pChannel)
			goto not_in_a_channel;
		pChannel->Emote(pMe->GetChatName(), szMsg, lang );
		break;
	};
}
Exemple #14
0
bool CChat::JoinChannel(CChatChanMember * pMember, LPCTSTR pszChannel, LPCTSTR pszPassword)
{
	ADDTOCALLSTACK("CChat::JoinChannel");
	ASSERT(pMember != NULL);
	CClient * pMemberClient = pMember->GetClient();
	ASSERT(pMemberClient != NULL);

	// Are we in a channel now?
	CChatChannel * pCurrentChannel = pMember->GetChannel();
	if (pCurrentChannel != NULL)
	{
		// Is it the same channel as the one I'm already in?
		if (strcmp(pszChannel, pCurrentChannel->GetName()) == 0)
		{
			// Tell them and return
			pMember->SendChatMsg(CHATMSG_AlreadyInConference, pszChannel);
			return false;
		}
	}

	CChatChannel * pNewChannel = FindChannel(pszChannel);
	if (pNewChannel == NULL)
	{
		pMemberClient->addChatSystemMessage(CHATMSG_NoConference, pszChannel );
		return false;
	}

	// If there's a password, is it the correct one?
	if (strcmp(pNewChannel->GetPassword(), pszPassword) != 0)
	{
		pMemberClient->addChatSystemMessage(CHATMSG_IncorrectPassword);
		return false;
	}

	// Leave the old channel 1st
	// Remove from old channel (if any)
	if (pCurrentChannel != NULL)
	{
		// Remove myself from the channels list of members
		pCurrentChannel->RemoveMember(pMember);

		// If noone is left, tell the chat system to delete it from memory
		if (pCurrentChannel->m_Members.GetCount() <= 0)
		{
			// Am I the last one here? Delete it from all other clients?
			DeleteChannel(pCurrentChannel);
		}

		// Since we left, clear all members from our client that might be in our list from the channel we just left
		pMemberClient->addChatSystemMessage(CHATMSG_ClearMemberList);
	}

	// Now join a new channel
	// Add all the members of the channel to the clients list of channel participants
	pNewChannel->SendMembers(pMember);

	// Add ourself to the channels list of members
	if (!pNewChannel->AddMember(pMember))
		return false;

	// Set the channel name title bar
	pMemberClient->addChatSystemMessage(CHATMSG_UpdateChannelBar, pszChannel);

	// Now send out my name to all clients in this channel
	pNewChannel->SendThisMember(pMember);
	return true;
}
Exemple #15
0
void CChat::DoCommand(CChatChanMember * pBy, LPCTSTR szMsg)
{
	ADDTOCALLSTACK("CChat::DoCommand");
	static LPCTSTR const sm_szCmd_Chat[] =
	{
		"ALLKICK",
		"BC",
		"BCALL",
		"CHATSOK",
		"CLEARIGNORE",
		"KILLCHATS",
		"NOCHATS",
		"SYSMSG",
		"WHEREIS"
	};

	ASSERT(pBy != NULL);
	ASSERT(szMsg != NULL);

	TCHAR buffer[2048];
	ASSERT(strlen(szMsg) < COUNTOF(buffer));
	strcpy(buffer, szMsg);

	TCHAR * pszCommand = buffer;
	TCHAR * pszText = NULL;
	size_t iCommandLength = strlen(pszCommand);
	for (size_t i = 0; i < iCommandLength; i++)
	{
		ASSERT( i<COUNTOF(buffer));
		if (pszCommand[i] == ' ')
		{
			pszCommand[i] = 0;
			pszText = pszCommand + i + 1;
		}
	}

	CGString sFrom;
	CChatChannel * pChannel = pBy->GetChannel();
	CClient * pByClient = pBy->GetClient();
	ASSERT(pByClient != NULL);

	switch ( FindTableSorted( pszCommand, sm_szCmd_Chat, COUNTOF(sm_szCmd_Chat)))
	{
		case 0: // "ALLKICK"
		{
			if (pChannel == NULL)
			{
				pBy->SendChatMsg(CHATMSG_MustBeInAConference);
				return;
			}

			if (!pChannel->IsModerator(pBy->GetChatName()))
			{
				pBy->SendChatMsg(CHATMSG_MustHaveOps);
				return;
			}

			pChannel->KickAll(pBy);
			DecorateName(sFrom, NULL, true);
			pBy->SendChatMsg(CHATMSG_PlayerTalk, sFrom, "All members have been kicked!", "");
			return;
		}
		case 1: // "BC"
		{
			if ( ! pByClient->IsPriv( PRIV_GM ))
			{
	need_gm_privs:
				DecorateName(sFrom, NULL, true);
				pBy->SendChatMsg(CHATMSG_PlayerTalk, sFrom, "You need to have GM privs to use this command.");
				return;
			}

			Broadcast(pBy, pszText);
			return;
		}
		case 2: // "BCALL"
		{
			if ( ! pByClient->IsPriv( PRIV_GM ))
				goto need_gm_privs;

			Broadcast(pBy, pszText, "", true);
			return;
		}
		case 3: // "CHATSOK"
		{
			if ( ! pByClient->IsPriv( PRIV_GM ))
				goto need_gm_privs;

			if (!m_fChatsOK)
			{
				m_fChatsOK = true;
				Broadcast(NULL, "Conference creation is enabled.");
			}
			return;
		}
		case 4: // "CLEARIGNORE"
		{
			pBy->ClearIgnoreList();
			return;
		}
		case 5: // "KILLCHATS"
		{
			if ( ! pByClient->IsPriv( PRIV_GM ))
				goto need_gm_privs;

			KillChannels();
			return;
		}
		case 6: // "NOCHATS"
		{
			if ( ! pByClient->IsPriv( PRIV_GM ))
				goto need_gm_privs;

			if (m_fChatsOK)
			{
				Broadcast(NULL, "Conference creation is now disabled.");
				m_fChatsOK = false;
			}
			return;
		}
		case 7: // "SYSMSG"
		{
			if ( ! pByClient->IsPriv( PRIV_GM ))
				goto need_gm_privs;

			Broadcast(NULL, pszText, "", true);
			return;
		}
		case 8:	// "WHEREIS"
		{
			WhereIs(pBy, pszText);
			return;
		}
		default:
		{
			TCHAR *pszMsg = Str_GetTemp();
			sprintf(pszMsg, "Unknown command: '%s'", pszCommand);

			DecorateName(sFrom, NULL, true);
			pBy->SendChatMsg(CHATMSG_PlayerTalk, sFrom, pszMsg);
			return;
		}
	}
}
Exemple #16
0
void CChat::Action(CClient *pClient, const NCHAR *pszText, int len, CLanguageID lang)
{
	ADDTOCALLSTACK("CChat::Action");
	// ARGS:
	//  len = length of the pszText string in NCHAR's.

	if ( !(g_Cfg.m_iFeatureT2A & FEATURE_T2A_CHAT) )
		return;

	CChatMember *pMe = static_cast<CChatMember *>(pClient);
	CChatChannel *pChannel = pMe->GetChannel();

	TCHAR szFullText[MAX_TALK_BUFFER];
	CvtNUNICODEToSystem(szFullText, sizeof(szFullText), pszText, len);

	TCHAR *pszMsg = szFullText + 1;
	switch ( szFullText[0] )	// the 1st character is a command byte (join channel, leave channel, etc)
	{
		case CHATACT_ChangeChannelPassword:		// client shortcut: /pw
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->ChangePassword(pMe, pszMsg);
			break;
		}
		case CHATACT_LeaveChannel:
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->RemoveMember(pMe);
			break;
		}
		case CHATACT_LeaveChat:
		{
			if ( pChannel )
				pChannel->RemoveMember(pMe);
			break;
		}
		case CHATACT_ChannelMessage:
		{
			if ( pChannel )
			{
				pChannel->MemberTalk(pMe, pClient->m_UseNewChatSystem ? szFullText : pszMsg, lang);
				break;
			}
		NoConference:
			pMe->SendChatMsg(CHATMSG_MustBeInAConference);
			return;
		}
		case CHATACT_JoinChannel:				// client shortcut: /conf
		{
			// Look for second double quote to separate channel from password
			size_t i = 1;
			for ( ; pszMsg[i] != '\0'; i++ )
			{
				if ( pszMsg[i] == '"' )
					break;
			}
			pszMsg[i] = '\0';
			TCHAR *pszPassword = pszMsg + i + 1;
			if ( pszPassword[0] == ' ' )	// skip whitespaces
				pszPassword++;
			JoinChannel(pszMsg + 1, pszPassword, pMe);
			break;
		}
		case CHATACT_CreateChannel:				// client shortcut: /newconf
		{
			TCHAR *pszPassword = NULL;
			size_t iMsgLength = strlen(pszMsg);
			for ( size_t i = 0; i < iMsgLength; i++ )
			{
				if ( pszMsg[i] == '{' )	// there's a password here
				{
					pszMsg[i] = 0;
					pszPassword = pszMsg + i + 1;
					size_t iPasswordLength = strlen(pszPassword);
					for ( i = 0; i < iPasswordLength; i++ )
					{
						if ( pszPassword[i] == '}' )
						{
							pszPassword[i] = '\0';
							break;
						}
					}
					break;
				}
			}
			if ( CreateChannel(pszMsg, pszPassword, pMe) )
				JoinChannel(pszMsg, pszPassword, pMe);
			break;
		}
		case CHATACT_RenameChannel:				// client shortcut: /rename
		{
			if ( !pChannel )
				goto NoConference;

			pMe->RenameChannel(pszMsg);
			break;
		}
		case CHATACT_PrivateMessage:			// client shortcut: /msg
		{
			if ( !pChannel )
				goto NoConference;

			// Split the recipient from the message (look for a space)
			TCHAR buffer[2048];
			strcpy(buffer, pszMsg);
			size_t bufferLength = strlen(buffer);
			size_t i = 0;
			for ( ; i < bufferLength; i++ )
			{
				if ( buffer[i] == ' ' )
				{
					buffer[i] = '\0';
					break;
				}
			}
			pChannel->PrivateMessage(pMe, buffer, buffer + i + 1, lang);
			break;
		}
		case CHATACT_AddIgnore:					// client shortcut: +ignore
		{
			pMe->AddIgnore(pszMsg);
			break;
		}
		case CHATACT_RemoveIgnore:				// client shortcut: -ignore
		{
			pMe->RemoveIgnore(pszMsg);
			break;
		}
		case CHATACT_ToggleIgnore:				// client shortcut: /ignore
		{
			pMe->ToggleIgnore(pszMsg);
			break;
		}
		case CHATACT_AddVoice:					// client shortcut: +voice
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->AddVoice(pMe, pszMsg);
			break;
		}
		case CHATACT_RemoveVoice:				// client shortcut: -voice
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->RemoveVoice(pMe, pszMsg);
			break;
		}
		case CHATACT_ToggleVoice:				// client shortcut: /voice
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->ToggleVoice(pMe, pszMsg);
			break;
		}
		case CHATACT_AddModerator:				// client shortcut: +ops
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->AddModerator(pMe, pszMsg);
			break;
		}
		case CHATACT_RemoveModerator:			// client shortcut: -ops
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->RemoveModerator(pMe, pszMsg);
			break;
		}
		case CHATACT_ToggleModerator:			// client shortcut: /ops
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->ToggleModerator(pMe, pszMsg);
			break;
		}
		case CHATACT_EnablePrivateMessages:		// client shortcut: +receive
		{
			pMe->SetReceiving(true);
			break;
		}
		case CHATACT_DisablePrivateMessages:	// client shortcut: -receive
		{
			pMe->SetReceiving(false);
			break;
		}
		case CHATACT_TogglePrivateMessages:		// client shortcut: /receive
		{
			pMe->ToggleReceiving();
			break;
		}
		case CHATACT_ShowCharacterName:			// client shortcut: +showname
		{
			pMe->ShowCharacterName();
			break;
		}
		case CHATACT_HideCharacterName:			// client shortcut: -showname
		{
			pMe->HideCharacterName();
			break;
		}
		case CHATACT_ToggleCharacterName:		// client shortcut: /showname
		{
			pMe->ToggleCharacterName();
			break;
		}
		case CHATACT_WhoIs:						// client shortcut: /whois
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->WhoIs(pMe->GetChatName(), pszMsg);
			break;
		}
		case CHATACT_Kick:						// client shortcut: /kick
		{
			if ( !pChannel )
				goto NoConference;

			CChatMember *pMember = pChannel->FindMember(pszMsg);
			if ( pMember )
				pChannel->KickMember(pMe, pMember);
			else
				pMe->SendChatMsg(CHATMSG_NoPlayer, pszMsg);
			break;
		}
		case CHATACT_EnableDefaultVoice:		// client shortcut: +defaultvoice
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->EnableDefaultVoice(pMe->GetChatName());
			break;
		}
		case CHATACT_DisableDefaultVoice:		// client shortcut: -defaultvoice
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->DisableDefaultVoice(pMe->GetChatName());
			break;
		}
		case CHATACT_ToggleDefaultVoice:		// client shortcut: /defaultvoice
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->ToggleDefaultVoice(pMe->GetChatName());
			break;
		}
		case CHATACT_EmoteMessage:				// client shortcut: /emote or /em
		{
			if ( !pChannel )
				goto NoConference;

			pChannel->Emote(pMe->GetChatName(), pszMsg, lang);
			break;
		}
	}
}