mirror of
https://github.com/HikikoMarmy/Champions-Reborn-Server.git
synced 2026-04-05 08:59:54 -03:00
Chat Room Support
This commit is contained in:
@@ -1,15 +1,77 @@
|
||||
#include "ChatRoomSession.h"
|
||||
|
||||
#include "RealmUser.h"
|
||||
|
||||
ChatRoomSession::ChatRoomSession()
|
||||
{
|
||||
m_type = GameType::Public;
|
||||
m_gameIndex = 0;
|
||||
m_gameName.clear();
|
||||
m_type = RoomType::Public;
|
||||
m_index = 0;
|
||||
m_name.clear();
|
||||
}
|
||||
|
||||
ChatRoomSession::~ChatRoomSession()
|
||||
{
|
||||
m_type = GameType::Public;
|
||||
m_gameIndex = 0;
|
||||
m_gameName.clear();
|
||||
m_type = RoomType::Public;
|
||||
m_index = 0;
|
||||
m_name.clear();
|
||||
}
|
||||
|
||||
bool ChatRoomSession::AddMember( sptr_user user )
|
||||
{
|
||||
if( !user )
|
||||
return false;
|
||||
|
||||
for( const auto &member : m_members )
|
||||
{
|
||||
if( member.lock() == user )
|
||||
return false; // User already in the room.
|
||||
}
|
||||
|
||||
m_members.push_back( user );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatRoomSession::RemoveMember( sptr_user user )
|
||||
{
|
||||
if( !user )
|
||||
return false;
|
||||
|
||||
auto it = std::remove_if( m_members.begin(), m_members.end(),
|
||||
[ &user ]( const std::weak_ptr< RealmUser > &member )
|
||||
{
|
||||
return member.lock() == user;
|
||||
} );
|
||||
|
||||
if( it == m_members.end() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_members.erase( it, m_members.end() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatRoomSession::IsMember( sptr_user user )
|
||||
{
|
||||
if( !user )
|
||||
return false;
|
||||
|
||||
for( const auto &member : m_members )
|
||||
{
|
||||
if( member.lock() == user )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChatRoomSession::IsPublic() const
|
||||
{
|
||||
return m_type == RoomType::Public;
|
||||
}
|
||||
|
||||
bool ChatRoomSession::IsPrivate() const
|
||||
{
|
||||
return m_type == RoomType::Private;
|
||||
}
|
||||
@@ -2,141 +2,294 @@
|
||||
|
||||
#include "RealmUser.h"
|
||||
|
||||
#include "../Network/Event/NotifyRoomMessage.h"
|
||||
#include "../logging.h"
|
||||
|
||||
ChatRoomManager::ChatRoomManager()
|
||||
{
|
||||
m_chatIndex = 0;
|
||||
m_chatSessionList.clear();
|
||||
m_roomIndex = 0;
|
||||
|
||||
CreatePublicRooms();
|
||||
}
|
||||
|
||||
ChatRoomManager::~ChatRoomManager()
|
||||
{
|
||||
}
|
||||
|
||||
void ChatRoomManager::CreatePublicRooms()
|
||||
{
|
||||
std::vector< std::wstring > RoomNames = {
|
||||
L"Champions Reborn",
|
||||
L"Adventurous",
|
||||
L"Courageous",
|
||||
L"Champion",
|
||||
L"Legendary",
|
||||
L"Epic"
|
||||
};
|
||||
|
||||
for( const auto &name : RoomNames )
|
||||
{
|
||||
auto new_session = std::make_shared< ChatRoomSession >();
|
||||
|
||||
new_session->m_name = name;
|
||||
new_session->m_type = ChatRoomSession::RoomType::Public;
|
||||
new_session->m_index = m_roomIndex;
|
||||
new_session->m_banner = L"";
|
||||
|
||||
m_chatSessionList[ m_roomIndex++ ] = new_session;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<sptr_chat_room_session> ChatRoomManager::GetPublicRoomList() const
|
||||
{
|
||||
std::vector< sptr_chat_room_session > result;
|
||||
|
||||
for( const auto &chatSession : m_chatSessionList )
|
||||
{
|
||||
if( chatSession.second->m_type == ChatRoomSession::RoomType::Public )
|
||||
{
|
||||
result.push_back( chatSession.second );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ChatRoomManager::JoinRoom( sptr_user user, const std::wstring &roomName )
|
||||
{
|
||||
if( roomName.empty() || !user )
|
||||
return false;
|
||||
|
||||
auto chatSession = FindRoom( roomName );
|
||||
if( !chatSession )
|
||||
{
|
||||
Log::Error( "Chat room [{}] not found", roomName );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !chatSession->AddMember( user ) )
|
||||
{
|
||||
Log::Error( "Failed to add user [{}] to chat room [{}]", user->m_username, roomName );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( chatSession->m_type == ChatRoomSession::RoomType::Public )
|
||||
{
|
||||
user->m_publicRoomId = chatSession->m_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
user->m_privateRoomId = chatSession->m_index;
|
||||
|
||||
SendMessageToRoom( roomName, L"", L"User '" + user->m_chatHandle + L"' has joined the room." );
|
||||
}
|
||||
|
||||
Log::Info( "User [{}] joined chat room [{}]", user->m_username, roomName );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatRoomManager::LeaveRoom( sptr_user user, const std::wstring &roomName )
|
||||
{
|
||||
if( !user || roomName.empty() )
|
||||
return false;
|
||||
|
||||
auto chatSession = FindRoom( roomName );
|
||||
if( !chatSession )
|
||||
{
|
||||
Log::Error( "Chat room [{}] not found", roomName );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !chatSession->RemoveMember( user ) )
|
||||
{
|
||||
Log::Error( "Failed to remove user [{}] from chat room [{}]", user->m_username, roomName );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( chatSession->m_type == ChatRoomSession::RoomType::Private )
|
||||
{
|
||||
if( chatSession->m_members.empty() && chatSession->m_moderators.empty() )
|
||||
{
|
||||
m_chatSessionList.erase( chatSession->m_index );
|
||||
|
||||
Log::Debug( "Private chat room [{}] deleted", roomName );
|
||||
}
|
||||
|
||||
user->m_privateRoomId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
user->m_publicRoomId = -1;
|
||||
}
|
||||
|
||||
Log::Info( "User [{}] left chat room [{}]", user->m_username, roomName );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatRoomManager::LeaveRoom( sptr_user user, const int32_t roomId )
|
||||
{
|
||||
if( !user || roomId < 0 )
|
||||
return false;
|
||||
|
||||
const auto chatSession = FindRoom( roomId );
|
||||
if( !chatSession )
|
||||
{
|
||||
Log::Error( "Chat room with ID [{}] not found", roomId );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !chatSession->RemoveMember( user ) )
|
||||
{
|
||||
Log::Error( "Failed to remove user [{}] from chat room with ID [{}]", user->m_username, roomId );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( chatSession->m_type == ChatRoomSession::RoomType::Private )
|
||||
{
|
||||
if( chatSession->m_members.empty() && chatSession->m_moderators.empty() )
|
||||
{
|
||||
m_chatSessionList.erase( roomId );
|
||||
Log::Info( "Private chat room with ID [{}] deleted", roomId );
|
||||
}
|
||||
|
||||
user->m_privateRoomId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
user->m_publicRoomId = -1;
|
||||
}
|
||||
|
||||
Log::Info( "User [{}] left chat room with ID [{}]", user->m_username, roomId );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChatRoomManager::OnDisconnectUser( sptr_user user )
|
||||
{
|
||||
if( !user || user->m_gameId < 0 )
|
||||
return;
|
||||
if( !user ) return;
|
||||
|
||||
const auto gameId = user->m_gameId;
|
||||
|
||||
auto session = FindRoom( gameId );
|
||||
if( !session )
|
||||
return;
|
||||
|
||||
//auto owner = session->m_owner.lock();
|
||||
//if( !owner )
|
||||
//{
|
||||
// Log::Error( "Game session owner not found! [%d]", gameId );
|
||||
// ForceTerminateChat( gameId );
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//if( owner->m_sessionId == user->m_sessionId )
|
||||
//{
|
||||
// Log::Info( "Game session owner disconnected! [%d]", gameId );
|
||||
// ForceTerminateChat( gameId );
|
||||
//}
|
||||
LeaveRoom( user, user->m_publicRoomId );
|
||||
LeaveRoom( user, user->m_privateRoomId );
|
||||
}
|
||||
|
||||
bool ChatRoomManager::CreatePublicChatSession( sptr_user owner, std::wstring gameName )
|
||||
bool ChatRoomManager::CreateGameChatSession( sptr_user owner, std::wstring roomName )
|
||||
{
|
||||
auto new_session = std::make_shared< ChatRoomSession >();
|
||||
|
||||
new_session->m_type = ChatRoomSession::GameType::Public;
|
||||
new_session->m_gameIndex = m_chatIndex;
|
||||
new_session->m_gameName = L"";
|
||||
|
||||
std::lock_guard< std::mutex > lock( m_mutex );
|
||||
m_chatSessionList.push_back( new_session );
|
||||
|
||||
m_chatIndex++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatRoomManager::CreatePrivateChatSession( sptr_user owner, std::wstring roomName )
|
||||
for( const auto &chatSession : m_chatSessionList )
|
||||
{
|
||||
for( auto &chatSession : m_chatSessionList )
|
||||
if( chatSession.second->m_name == roomName )
|
||||
{
|
||||
if( chatSession->m_type != ChatRoomSession::GameType::Private )
|
||||
continue;
|
||||
|
||||
if( chatSession->m_gameName == roomName )
|
||||
{
|
||||
Log::Error( "Game name is already in use! [%S]", roomName.c_str() );
|
||||
Log::Error( "Chat Room name is already in use! [{}]", roomName );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto new_session = std::make_shared< ChatRoomSession >();
|
||||
|
||||
new_session->m_type = ChatRoomSession::GameType::Private;
|
||||
new_session->m_gameIndex = m_chatIndex;
|
||||
new_session->m_gameName = roomName;
|
||||
new_session->m_type = ChatRoomSession::RoomType::Private;
|
||||
new_session->m_name = roomName;
|
||||
new_session->m_owner = owner;
|
||||
new_session->m_banner = L"";
|
||||
new_session->m_index = m_roomIndex;
|
||||
|
||||
std::lock_guard< std::mutex > lock( m_mutex );
|
||||
m_chatSessionList.push_back( new_session );
|
||||
new_session->AddMember( owner );
|
||||
owner->m_privateRoomId = m_roomIndex;
|
||||
|
||||
m_chatIndex++;
|
||||
m_chatSessionList[ m_roomIndex++ ] = new_session;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatRoomManager::ForceTerminateChat( const int32_t gameId )
|
||||
{
|
||||
if( gameId < 0 )
|
||||
bool ChatRoomManager::CloseGameChatSession( const std::wstring roomName )
|
||||
{
|
||||
if( roomName.empty() )
|
||||
return false;
|
||||
}
|
||||
|
||||
std::lock_guard< std::mutex > lock( m_mutex );
|
||||
|
||||
auto it = std::find_if( m_chatSessionList.begin(), m_chatSessionList.end(), [ &gameId ]( sptr_chat_room_session chatSession )
|
||||
const auto it = std::find_if( m_chatSessionList.begin(), m_chatSessionList.end(),
|
||||
[ &roomName ]( const auto &pair )
|
||||
{
|
||||
return chatSession->m_gameIndex == gameId;
|
||||
return pair.second->m_name == roomName;
|
||||
} );
|
||||
|
||||
if( it != m_chatSessionList.end() )
|
||||
if( it == m_chatSessionList.end() )
|
||||
{
|
||||
m_chatSessionList.erase( it );
|
||||
return true;
|
||||
}
|
||||
|
||||
Log::Error( "Chat room [{}] not found", roomName );
|
||||
return false;
|
||||
}
|
||||
|
||||
sptr_chat_room_session ChatRoomManager::FindRoom( const int32_t gameId )
|
||||
auto &chatSession = it->second;
|
||||
if( chatSession->m_type != ChatRoomSession::RoomType::Private )
|
||||
{
|
||||
if( gameId < 0 ) return nullptr;
|
||||
Log::Error( "Chat room [{}] is not a private room", roomName );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::lock_guard< std::mutex > lock( m_mutex );
|
||||
|
||||
for( auto &chatSession : m_chatSessionList )
|
||||
for( const auto &member : chatSession->m_members )
|
||||
{
|
||||
if( chatSession->m_gameIndex == gameId )
|
||||
if( auto user = member.lock() )
|
||||
{
|
||||
return chatSession;
|
||||
user->m_privateRoomId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
m_chatSessionList.erase( it );
|
||||
|
||||
Log::Info( "Chat room [{}] closed", roomName );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChatRoomManager::SendMessageToRoom( std::wstring roomName, std::wstring handle, std::wstring message )
|
||||
{
|
||||
if( roomName.empty() || message.empty() )
|
||||
return;
|
||||
|
||||
auto chatSession = FindRoom( roomName );
|
||||
if( !chatSession )
|
||||
{
|
||||
Log::Error( "Chat room [{}] not found", roomName );
|
||||
return;
|
||||
}
|
||||
|
||||
NotifyRoomMessage notifyMessage( roomName, handle, message );
|
||||
for( const auto &m : chatSession->m_members )
|
||||
{
|
||||
if( auto member = m.lock() )
|
||||
{
|
||||
member->sock->send( notifyMessage );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sptr_chat_room_session ChatRoomManager::FindRoom( const std::wstring &gameName )
|
||||
{
|
||||
if( gameName.empty() ) return nullptr;
|
||||
if( gameName.empty() )
|
||||
return nullptr;
|
||||
|
||||
std::lock_guard< std::mutex > lock( m_mutex );
|
||||
|
||||
for( auto &chatSession : m_chatSessionList )
|
||||
for( const auto &chatSession : m_chatSessionList )
|
||||
{
|
||||
if( chatSession->m_gameName == gameName )
|
||||
if( chatSession.second->m_name == gameName )
|
||||
{
|
||||
return chatSession;
|
||||
return chatSession.second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sptr_chat_room_session ChatRoomManager::FindRoom( const int32_t roomId )
|
||||
{
|
||||
if( roomId < 0 )
|
||||
return nullptr;
|
||||
|
||||
auto it = m_chatSessionList.find( roomId );
|
||||
|
||||
if( it != m_chatSessionList.end() )
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Log::Error( "Chat room with ID [{}] not found", roomId );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -2,19 +2,17 @@
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "ChatRoomSession.h"
|
||||
|
||||
class ChatRoomManager {
|
||||
private:
|
||||
static inline std::unique_ptr< ChatRoomManager > m_instance;
|
||||
static inline std::mutex m_mutex;
|
||||
|
||||
int32_t m_chatIndex;
|
||||
std::vector< sptr_chat_room_session > m_chatSessionList;
|
||||
int32_t m_roomIndex = 0;
|
||||
std::map< int32_t, sptr_chat_room_session > m_chatSessionList;
|
||||
|
||||
void CreatePublicRooms();
|
||||
public:
|
||||
ChatRoomManager();
|
||||
~ChatRoomManager();
|
||||
@@ -23,20 +21,22 @@ public:
|
||||
|
||||
static ChatRoomManager &Get()
|
||||
{
|
||||
std::lock_guard< std::mutex > lock( m_mutex );
|
||||
if( m_instance == nullptr )
|
||||
{
|
||||
m_instance.reset( new ChatRoomManager() );
|
||||
static ChatRoomManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
return *m_instance;
|
||||
}
|
||||
std::vector< sptr_chat_room_session > GetPublicRoomList() const;
|
||||
|
||||
bool JoinRoom( sptr_user user, const std::wstring &roomName );
|
||||
bool LeaveRoom( sptr_user user, const std::wstring &roomName );
|
||||
bool LeaveRoom( sptr_user user, const int32_t roomId );
|
||||
|
||||
void OnDisconnectUser( sptr_user user );
|
||||
bool CreateGameChatSession( sptr_user user, const std::wstring roomName );
|
||||
bool CloseGameChatSession( const std::wstring roomName );
|
||||
|
||||
void SendMessageToRoom( const std::wstring roomName, const std::wstring handle, const std::wstring message );
|
||||
|
||||
bool CreatePublicChatSession( sptr_user user, std::wstring roomName );
|
||||
bool CreatePrivateChatSession( sptr_user user, std::wstring roomName );
|
||||
bool ForceTerminateChat( const int32_t gameId );
|
||||
sptr_chat_room_session FindRoom( const int32_t gameId );
|
||||
sptr_chat_room_session FindRoom( const std::wstring &roomName );
|
||||
sptr_chat_room_session FindRoom( const int32_t roomId );
|
||||
};
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "RealmUser.h"
|
||||
|
||||
class ChatRoomSession {
|
||||
@@ -9,16 +11,26 @@ public:
|
||||
ChatRoomSession();
|
||||
~ChatRoomSession();
|
||||
|
||||
enum class GameType
|
||||
{
|
||||
bool AddMember( sptr_user user );
|
||||
bool RemoveMember( sptr_user user );
|
||||
bool IsMember( sptr_user user );
|
||||
bool IsPublic() const;
|
||||
bool IsPrivate() const;
|
||||
|
||||
enum class RoomType {
|
||||
Public,
|
||||
Private
|
||||
} m_type;
|
||||
};
|
||||
|
||||
int32_t m_gameIndex;
|
||||
std::wstring m_gameName;
|
||||
RoomType m_type;
|
||||
int32_t m_index;
|
||||
|
||||
std::weak_ptr< RealmUser > m_owner;
|
||||
std::wstring m_name;
|
||||
std::wstring m_banner;
|
||||
|
||||
wptr_user m_owner;
|
||||
std::vector< wptr_user > m_members;
|
||||
std::vector< wptr_user > m_moderators;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr< ChatRoomSession > sptr_chat_room_session;
|
||||
Reference in New Issue
Block a user