mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	network/room_member: Add moderation functions
To allow for passing moderation errors around without impacting the State, this commit also separates the previous State enum into two enums: State, and Error. The State enum now only contains generic states like disconnected or connected, and the Error enum describes the specific error happened.
citra_qt/multiplayer/{state, message} is changed accordingly.
			
			
This commit is contained in:
		
							parent
							
								
									38f86cce94
								
							
						
					
					
						commit
						7acd2664dd
					
				
					 6 changed files with 251 additions and 56 deletions
				
			
		|  | @ -36,11 +36,16 @@ const ConnectionError WRONG_PASSWORD(QT_TR_NOOP("Incorrect password.")); | ||||||
| const ConnectionError GENERIC_ERROR( | const ConnectionError GENERIC_ERROR( | ||||||
|     QT_TR_NOOP("An unknown error occured. If this error continues to occur, please open an issue")); |     QT_TR_NOOP("An unknown error occured. If this error continues to occur, please open an issue")); | ||||||
| const ConnectionError LOST_CONNECTION(QT_TR_NOOP("Connection to room lost. Try to reconnect.")); | const ConnectionError LOST_CONNECTION(QT_TR_NOOP("Connection to room lost. Try to reconnect.")); | ||||||
|  | const ConnectionError HOST_KICKED(QT_TR_NOOP("You have been kicked by the room host.")); | ||||||
| const ConnectionError MAC_COLLISION( | const ConnectionError MAC_COLLISION( | ||||||
|     QT_TR_NOOP("MAC address is already in use. Please choose another.")); |     QT_TR_NOOP("MAC address is already in use. Please choose another.")); | ||||||
| const ConnectionError CONSOLE_ID_COLLISION(QT_TR_NOOP( | const ConnectionError CONSOLE_ID_COLLISION(QT_TR_NOOP( | ||||||
|     "Your Console ID conflicted with someone else's in the room.\n\nPlease go to Emulation " |     "Your Console ID conflicted with someone else's in the room.\n\nPlease go to Emulation " | ||||||
|     "> Configure > System to regenerate your Console ID.")); |     "> Configure > System to regenerate your Console ID.")); | ||||||
|  | const ConnectionError PERMISSION_DENIED( | ||||||
|  |     QT_TR_NOOP("You do not have enough permission to perform this action.")); | ||||||
|  | const ConnectionError NO_SUCH_USER(QT_TR_NOOP( | ||||||
|  |     "The user you are trying to kick/ban could not be found.\nThey may have left the room.")); | ||||||
| 
 | 
 | ||||||
| static bool WarnMessage(const std::string& title, const std::string& text) { | static bool WarnMessage(const std::string& title, const std::string& text) { | ||||||
|     return QMessageBox::Ok == QMessageBox::warning(nullptr, QObject::tr(title.c_str()), |     return QMessageBox::Ok == QMessageBox::warning(nullptr, QObject::tr(title.c_str()), | ||||||
|  |  | ||||||
|  | @ -36,8 +36,11 @@ extern const ConnectionError WRONG_VERSION; | ||||||
| extern const ConnectionError WRONG_PASSWORD; | extern const ConnectionError WRONG_PASSWORD; | ||||||
| extern const ConnectionError GENERIC_ERROR; | extern const ConnectionError GENERIC_ERROR; | ||||||
| extern const ConnectionError LOST_CONNECTION; | extern const ConnectionError LOST_CONNECTION; | ||||||
|  | extern const ConnectionError HOST_KICKED; | ||||||
| extern const ConnectionError MAC_COLLISION; | extern const ConnectionError MAC_COLLISION; | ||||||
| extern const ConnectionError CONSOLE_ID_COLLISION; | extern const ConnectionError CONSOLE_ID_COLLISION; | ||||||
|  | extern const ConnectionError PERMISSION_DENIED; | ||||||
|  | extern const ConnectionError NO_SUCH_USER; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  *  Shows a standard QMessageBox with a error message |  *  Shows a standard QMessageBox with a error message | ||||||
|  |  | ||||||
|  | @ -27,9 +27,13 @@ MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_lis | ||||||
|             [this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); }); |             [this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); }); | ||||||
|         connect(this, &MultiplayerState::NetworkStateChanged, this, |         connect(this, &MultiplayerState::NetworkStateChanged, this, | ||||||
|                 &MultiplayerState::OnNetworkStateChanged); |                 &MultiplayerState::OnNetworkStateChanged); | ||||||
|  |         error_callback_handle = member->BindOnError( | ||||||
|  |             [this](const Network::RoomMember::Error& error) { emit NetworkError(error); }); | ||||||
|  |         connect(this, &MultiplayerState::NetworkError, this, &MultiplayerState::OnNetworkError); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     qRegisterMetaType<Network::RoomMember::State>(); |     qRegisterMetaType<Network::RoomMember::State>(); | ||||||
|  |     qRegisterMetaType<Network::RoomMember::Error>(); | ||||||
|     qRegisterMetaType<Common::WebResult>(); |     qRegisterMetaType<Common::WebResult>(); | ||||||
|     announce_multiplayer_session = std::make_shared<Core::AnnounceMultiplayerSession>(); |     announce_multiplayer_session = std::make_shared<Core::AnnounceMultiplayerSession>(); | ||||||
|     announce_multiplayer_session->BindErrorCallback( |     announce_multiplayer_session->BindErrorCallback( | ||||||
|  | @ -52,6 +56,12 @@ MultiplayerState::~MultiplayerState() { | ||||||
|             member->Unbind(state_callback_handle); |             member->Unbind(state_callback_handle); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     if (error_callback_handle) { | ||||||
|  |         if (auto member = Network::GetRoomMember().lock()) { | ||||||
|  |             member->Unbind(error_callback_handle); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MultiplayerState::Close() { | void MultiplayerState::Close() { | ||||||
|  | @ -88,41 +98,8 @@ void MultiplayerState::retranslateUi() { | ||||||
| 
 | 
 | ||||||
| void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& state) { | void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& state) { | ||||||
|     LOG_DEBUG(Frontend, "Network State: {}", Network::GetStateStr(state)); |     LOG_DEBUG(Frontend, "Network State: {}", Network::GetStateStr(state)); | ||||||
|     bool is_connected = false; |     if (state == Network::RoomMember::State::Joined) { | ||||||
|     switch (state) { |  | ||||||
|     case Network::RoomMember::State::LostConnection: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::LOST_CONNECTION); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::CouldNotConnect: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::UNABLE_TO_CONNECT); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::NameCollision: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::USERNAME_NOT_VALID_SERVER); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::MacCollision: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::MAC_COLLISION); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::ConsoleIdCollision: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::CONSOLE_ID_COLLISION); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::RoomIsFull: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::ROOM_IS_FULL); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::WrongPassword: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::WRONG_PASSWORD); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::WrongVersion: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::WRONG_VERSION); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::Error: |  | ||||||
|         NetworkMessage::ShowError(NetworkMessage::UNABLE_TO_CONNECT); |  | ||||||
|         break; |  | ||||||
|     case Network::RoomMember::State::Joined: |  | ||||||
|         is_connected = true; |  | ||||||
|         OnOpenNetworkRoom(); |         OnOpenNetworkRoom(); | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     if (is_connected) { |  | ||||||
|         status_icon->setPixmap(QIcon::fromTheme("connected").pixmap(16)); |         status_icon->setPixmap(QIcon::fromTheme("connected").pixmap(16)); | ||||||
|         status_text->setText(tr("Connected")); |         status_text->setText(tr("Connected")); | ||||||
|         leave_room->setEnabled(true); |         leave_room->setEnabled(true); | ||||||
|  | @ -137,6 +114,51 @@ void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& s | ||||||
|     current_state = state; |     current_state = state; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MultiplayerState::OnNetworkError(const Network::RoomMember::Error& error) { | ||||||
|  |     LOG_DEBUG(Frontend, "Network Error: {}", Network::GetErrorStr(error)); | ||||||
|  |     switch (error) { | ||||||
|  |     case Network::RoomMember::Error::LostConnection: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::LOST_CONNECTION); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::HostKicked: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::HOST_KICKED); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::CouldNotConnect: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::UNABLE_TO_CONNECT); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::NameCollision: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::USERNAME_NOT_VALID_SERVER); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::MacCollision: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::MAC_COLLISION); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::ConsoleIdCollision: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::CONSOLE_ID_COLLISION); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::RoomIsFull: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::ROOM_IS_FULL); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::WrongPassword: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::WRONG_PASSWORD); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::WrongVersion: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::WRONG_VERSION); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::HostBanned: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::HOST_BANNED); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::UnknownError: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::UNABLE_TO_CONNECT); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::PermissionDenied: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::PERMISSION_DENIED); | ||||||
|  |         break; | ||||||
|  |     case Network::RoomMember::Error::NoSuchUser: | ||||||
|  |         NetworkMessage::ShowError(NetworkMessage::NO_SUCH_USER); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void MultiplayerState::OnAnnounceFailed(const Common::WebResult& result) { | void MultiplayerState::OnAnnounceFailed(const Common::WebResult& result) { | ||||||
|     announce_multiplayer_session->Stop(); |     announce_multiplayer_session->Stop(); | ||||||
|     QMessageBox::warning( |     QMessageBox::warning( | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ public: | ||||||
| 
 | 
 | ||||||
| public slots: | public slots: | ||||||
|     void OnNetworkStateChanged(const Network::RoomMember::State& state); |     void OnNetworkStateChanged(const Network::RoomMember::State& state); | ||||||
|  |     void OnNetworkError(const Network::RoomMember::Error& error); | ||||||
|     void OnViewLobby(); |     void OnViewLobby(); | ||||||
|     void OnCreateRoom(); |     void OnCreateRoom(); | ||||||
|     bool OnCloseRoom(); |     bool OnCloseRoom(); | ||||||
|  | @ -50,6 +51,7 @@ public slots: | ||||||
| 
 | 
 | ||||||
| signals: | signals: | ||||||
|     void NetworkStateChanged(const Network::RoomMember::State&); |     void NetworkStateChanged(const Network::RoomMember::State&); | ||||||
|  |     void NetworkError(const Network::RoomMember::Error&); | ||||||
|     void AnnounceFailed(const Common::WebResult&); |     void AnnounceFailed(const Common::WebResult&); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  | @ -65,6 +67,7 @@ private: | ||||||
|     std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; |     std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; | ||||||
|     Network::RoomMember::State current_state = Network::RoomMember::State::Uninitialized; |     Network::RoomMember::State current_state = Network::RoomMember::State::Uninitialized; | ||||||
|     Network::RoomMember::CallbackHandle<Network::RoomMember::State> state_callback_handle; |     Network::RoomMember::CallbackHandle<Network::RoomMember::State> state_callback_handle; | ||||||
|  |     Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Q_DECLARE_METATYPE(Common::WebResult); | Q_DECLARE_METATYPE(Common::WebResult); | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     std::atomic<State> state{State::Idle}; ///< Current state of the RoomMember.
 |     std::atomic<State> state{State::Idle}; ///< Current state of the RoomMember.
 | ||||||
|     void SetState(const State new_state); |     void SetState(const State new_state); | ||||||
|  |     void SetError(const Error new_error); | ||||||
|     bool IsConnected() const; |     bool IsConnected() const; | ||||||
| 
 | 
 | ||||||
|     std::string nickname; ///< The nickname of this member.
 |     std::string nickname; ///< The nickname of this member.
 | ||||||
|  | @ -61,6 +62,8 @@ public: | ||||||
|         CallbackSet<StatusMessageEntry> callback_set_status_messages; |         CallbackSet<StatusMessageEntry> callback_set_status_messages; | ||||||
|         CallbackSet<RoomInformation> callback_set_room_information; |         CallbackSet<RoomInformation> callback_set_room_information; | ||||||
|         CallbackSet<State> callback_set_state; |         CallbackSet<State> callback_set_state; | ||||||
|  |         CallbackSet<Error> callback_set_error; | ||||||
|  |         CallbackSet<Room::BanList> callback_set_ban_list; | ||||||
|     }; |     }; | ||||||
|     Callbacks callbacks; ///< All CallbackSets to all events
 |     Callbacks callbacks; ///< All CallbackSets to all events
 | ||||||
| 
 | 
 | ||||||
|  | @ -117,6 +120,12 @@ public: | ||||||
|      */ |      */ | ||||||
|     void HandleStatusMessagePacket(const ENetEvent* event); |     void HandleStatusMessagePacket(const ENetEvent* event); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Extracts a ban list request response from a received ENet packet. | ||||||
|  |      * @param event The ENet event that was received. | ||||||
|  |      */ | ||||||
|  |     void HandleModBanListResponsePacket(const ENetEvent* event); | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Disconnects the RoomMember from the Room |      * Disconnects the RoomMember from the Room | ||||||
|      */ |      */ | ||||||
|  | @ -137,6 +146,10 @@ void RoomMember::RoomMemberImpl::SetState(const State new_state) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RoomMember::RoomMemberImpl::SetError(const Error new_error) { | ||||||
|  |     Invoke<Error>(new_error); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool RoomMember::RoomMemberImpl::IsConnected() const { | bool RoomMember::RoomMemberImpl::IsConnected() const { | ||||||
|     return state == State::Joining || state == State::Joined; |     return state == State::Joining || state == State::Joined; | ||||||
| } | } | ||||||
|  | @ -170,32 +183,59 @@ void RoomMember::RoomMemberImpl::MemberLoop() { | ||||||
|                     HandleJoinPacket(&event); // Get the MAC Address for the client
 |                     HandleJoinPacket(&event); // Get the MAC Address for the client
 | ||||||
|                     SetState(State::Joined); |                     SetState(State::Joined); | ||||||
|                     break; |                     break; | ||||||
|  |                 case IdModBanListResponse: | ||||||
|  |                     HandleModBanListResponsePacket(&event); | ||||||
|  |                     break; | ||||||
|                 case IdRoomIsFull: |                 case IdRoomIsFull: | ||||||
|                     SetState(State::RoomIsFull); |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::RoomIsFull); | ||||||
|                     break; |                     break; | ||||||
|                 case IdNameCollision: |                 case IdNameCollision: | ||||||
|                     SetState(State::NameCollision); |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::NameCollision); | ||||||
|                     break; |                     break; | ||||||
|                 case IdMacCollision: |                 case IdMacCollision: | ||||||
|                     SetState(State::MacCollision); |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::MacCollision); | ||||||
|                     break; |                     break; | ||||||
|                 case IdConsoleIdCollision: |                 case IdConsoleIdCollision: | ||||||
|                     SetState(State::ConsoleIdCollision); |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::ConsoleIdCollision); | ||||||
|                     break; |                     break; | ||||||
|                 case IdVersionMismatch: |                 case IdVersionMismatch: | ||||||
|                     SetState(State::WrongVersion); |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::WrongVersion); | ||||||
|                     break; |                     break; | ||||||
|                 case IdWrongPassword: |                 case IdWrongPassword: | ||||||
|                     SetState(State::WrongPassword); |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::WrongPassword); | ||||||
|                     break; |                     break; | ||||||
|                 case IdCloseRoom: |                 case IdCloseRoom: | ||||||
|                     SetState(State::LostConnection); |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::LostConnection); | ||||||
|  |                     break; | ||||||
|  |                 case IdHostKicked: | ||||||
|  |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::HostKicked); | ||||||
|  |                     break; | ||||||
|  |                 case IdHostBanned: | ||||||
|  |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::HostBanned); | ||||||
|  |                     break; | ||||||
|  |                 case IdModPermissionDenied: | ||||||
|  |                     SetError(Error::PermissionDenied); | ||||||
|  |                     break; | ||||||
|  |                 case IdModNoSuchUser: | ||||||
|  |                     SetError(Error::NoSuchUser); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 enet_packet_destroy(event.packet); |                 enet_packet_destroy(event.packet); | ||||||
|                 break; |                 break; | ||||||
|             case ENET_EVENT_TYPE_DISCONNECT: |             case ENET_EVENT_TYPE_DISCONNECT: | ||||||
|                 SetState(State::LostConnection); |                 if (state == State::Joined) { | ||||||
|  |                     SetState(State::Idle); | ||||||
|  |                     SetError(Error::LostConnection); | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -251,11 +291,13 @@ void RoomMember::RoomMemberImpl::HandleRoomInformationPacket(const ENetEvent* ev | ||||||
|     packet >> info.member_slots; |     packet >> info.member_slots; | ||||||
|     packet >> info.port; |     packet >> info.port; | ||||||
|     packet >> info.preferred_game; |     packet >> info.preferred_game; | ||||||
|  |     packet >> info.host_username; | ||||||
|     room_information.name = info.name; |     room_information.name = info.name; | ||||||
|     room_information.description = info.description; |     room_information.description = info.description; | ||||||
|     room_information.member_slots = info.member_slots; |     room_information.member_slots = info.member_slots; | ||||||
|     room_information.port = info.port; |     room_information.port = info.port; | ||||||
|     room_information.preferred_game = info.preferred_game; |     room_information.preferred_game = info.preferred_game; | ||||||
|  |     room_information.host_username = info.host_username; | ||||||
| 
 | 
 | ||||||
|     u32 num_members; |     u32 num_members; | ||||||
|     packet >> num_members; |     packet >> num_members; | ||||||
|  | @ -344,6 +386,19 @@ void RoomMember::RoomMemberImpl::HandleStatusMessagePacket(const ENetEvent* even | ||||||
|     Invoke<StatusMessageEntry>(status_message_entry); |     Invoke<StatusMessageEntry>(status_message_entry); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RoomMember::RoomMemberImpl::HandleModBanListResponsePacket(const ENetEvent* event) { | ||||||
|  |     Packet packet; | ||||||
|  |     packet.Append(event->packet->data, event->packet->dataLength); | ||||||
|  | 
 | ||||||
|  |     // Ignore the first byte, which is the message id.
 | ||||||
|  |     packet.IgnoreBytes(sizeof(u8)); | ||||||
|  | 
 | ||||||
|  |     Room::BanList ban_list = {}; | ||||||
|  |     packet >> ban_list.first; | ||||||
|  |     packet >> ban_list.second; | ||||||
|  |     Invoke<Room::BanList>(ban_list); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void RoomMember::RoomMemberImpl::Disconnect() { | void RoomMember::RoomMemberImpl::Disconnect() { | ||||||
|     member_information.clear(); |     member_information.clear(); | ||||||
|     room_information.member_slots = 0; |     room_information.member_slots = 0; | ||||||
|  | @ -383,6 +438,12 @@ RoomMember::RoomMemberImpl::Callbacks::Get() { | ||||||
|     return callback_set_state; |     return callback_set_state; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <> | ||||||
|  | RoomMember::RoomMemberImpl::CallbackSet<RoomMember::Error>& | ||||||
|  | RoomMember::RoomMemberImpl::Callbacks::Get() { | ||||||
|  |     return callback_set_error; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| template <> | template <> | ||||||
| RoomMember::RoomMemberImpl::CallbackSet<RoomInformation>& | RoomMember::RoomMemberImpl::CallbackSet<RoomInformation>& | ||||||
| RoomMember::RoomMemberImpl::Callbacks::Get() { | RoomMember::RoomMemberImpl::Callbacks::Get() { | ||||||
|  | @ -400,6 +461,12 @@ RoomMember::RoomMemberImpl::Callbacks::Get() { | ||||||
|     return callback_set_status_messages; |     return callback_set_status_messages; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <> | ||||||
|  | RoomMember::RoomMemberImpl::CallbackSet<Room::BanList>& | ||||||
|  | RoomMember::RoomMemberImpl::Callbacks::Get() { | ||||||
|  |     return callback_set_ban_list; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| void RoomMember::RoomMemberImpl::Invoke(const T& data) { | void RoomMember::RoomMemberImpl::Invoke(const T& data) { | ||||||
|     std::lock_guard<std::mutex> lock(callback_mutex); |     std::lock_guard<std::mutex> lock(callback_mutex); | ||||||
|  | @ -481,7 +548,8 @@ void RoomMember::Join(const std::string& nick, const std::string& console_id_has | ||||||
|         enet_host_connect(room_member_impl->client, &address, NumChannels, 0); |         enet_host_connect(room_member_impl->client, &address, NumChannels, 0); | ||||||
| 
 | 
 | ||||||
|     if (!room_member_impl->server) { |     if (!room_member_impl->server) { | ||||||
|         room_member_impl->SetState(State::Error); |         room_member_impl->SetState(State::Idle); | ||||||
|  |         room_member_impl->SetError(Error::UnknownError); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -494,7 +562,8 @@ void RoomMember::Join(const std::string& nick, const std::string& console_id_has | ||||||
|         SendGameInfo(room_member_impl->current_game_info); |         SendGameInfo(room_member_impl->current_game_info); | ||||||
|     } else { |     } else { | ||||||
|         enet_peer_disconnect(room_member_impl->server, 0); |         enet_peer_disconnect(room_member_impl->server, 0); | ||||||
|         room_member_impl->SetState(State::CouldNotConnect); |         room_member_impl->SetState(State::Idle); | ||||||
|  |         room_member_impl->SetError(Error::CouldNotConnect); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -532,11 +601,37 @@ void RoomMember::SendGameInfo(const GameInfo& game_info) { | ||||||
|     room_member_impl->Send(std::move(packet)); |     room_member_impl->Send(std::move(packet)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RoomMember::SendModerationRequest(RoomMessageTypes type, const std::string& nickname) { | ||||||
|  |     ASSERT_MSG(type == IdModKick || type == IdModBan || type == IdModUnban, | ||||||
|  |                "type is not a moderation request"); | ||||||
|  |     if (!IsConnected()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     Packet packet; | ||||||
|  |     packet << static_cast<u8>(type); | ||||||
|  |     packet << nickname; | ||||||
|  |     room_member_impl->Send(std::move(packet)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RoomMember::RequestBanList() { | ||||||
|  |     if (!IsConnected()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     Packet packet; | ||||||
|  |     packet << static_cast<u8>(IdModGetBanList); | ||||||
|  |     room_member_impl->Send(std::move(packet)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| RoomMember::CallbackHandle<RoomMember::State> RoomMember::BindOnStateChanged( | RoomMember::CallbackHandle<RoomMember::State> RoomMember::BindOnStateChanged( | ||||||
|     std::function<void(const RoomMember::State&)> callback) { |     std::function<void(const RoomMember::State&)> callback) { | ||||||
|     return room_member_impl->Bind(callback); |     return room_member_impl->Bind(callback); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | RoomMember::CallbackHandle<RoomMember::Error> RoomMember::BindOnError( | ||||||
|  |     std::function<void(const RoomMember::Error&)> callback) { | ||||||
|  |     return room_member_impl->Bind(callback); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| RoomMember::CallbackHandle<WifiPacket> RoomMember::BindOnWifiPacketReceived( | RoomMember::CallbackHandle<WifiPacket> RoomMember::BindOnWifiPacketReceived( | ||||||
|     std::function<void(const WifiPacket&)> callback) { |     std::function<void(const WifiPacket&)> callback) { | ||||||
|     return room_member_impl->Bind(callback); |     return room_member_impl->Bind(callback); | ||||||
|  | @ -557,6 +652,11 @@ RoomMember::CallbackHandle<StatusMessageEntry> RoomMember::BindOnStatusMessageRe | ||||||
|     return room_member_impl->Bind(callback); |     return room_member_impl->Bind(callback); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | RoomMember::CallbackHandle<Room::BanList> RoomMember::BindOnBanListReceived( | ||||||
|  |     std::function<void(const Room::BanList&)> callback) { | ||||||
|  |     return room_member_impl->Bind(callback); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| void RoomMember::Unbind(CallbackHandle<T> handle) { | void RoomMember::Unbind(CallbackHandle<T> handle) { | ||||||
|     std::lock_guard<std::mutex> lock(room_member_impl->callback_mutex); |     std::lock_guard<std::mutex> lock(room_member_impl->callback_mutex); | ||||||
|  | @ -574,8 +674,10 @@ void RoomMember::Leave() { | ||||||
| 
 | 
 | ||||||
| template void RoomMember::Unbind(CallbackHandle<WifiPacket>); | template void RoomMember::Unbind(CallbackHandle<WifiPacket>); | ||||||
| template void RoomMember::Unbind(CallbackHandle<RoomMember::State>); | template void RoomMember::Unbind(CallbackHandle<RoomMember::State>); | ||||||
|  | template void RoomMember::Unbind(CallbackHandle<RoomMember::Error>); | ||||||
| template void RoomMember::Unbind(CallbackHandle<RoomInformation>); | template void RoomMember::Unbind(CallbackHandle<RoomInformation>); | ||||||
| template void RoomMember::Unbind(CallbackHandle<ChatEntry>); | template void RoomMember::Unbind(CallbackHandle<ChatEntry>); | ||||||
| template void RoomMember::Unbind(CallbackHandle<StatusMessageEntry>); | template void RoomMember::Unbind(CallbackHandle<StatusMessageEntry>); | ||||||
|  | template void RoomMember::Unbind(CallbackHandle<Room::BanList>); | ||||||
| 
 | 
 | ||||||
| } // namespace Network
 | } // namespace Network
 | ||||||
|  |  | ||||||
|  | @ -57,20 +57,30 @@ class RoomMember final { | ||||||
| public: | public: | ||||||
|     enum class State : u8 { |     enum class State : u8 { | ||||||
|         Uninitialized, ///< Not initialized
 |         Uninitialized, ///< Not initialized
 | ||||||
|         Idle,          ///< Default state
 |         Idle,          ///< Default state (i.e. not connected)
 | ||||||
|         Error,         ///< Some error [permissions to network device missing or something]
 |  | ||||||
|         Joining,       ///< The client is attempting to join a room.
 |         Joining,       ///< The client is attempting to join a room.
 | ||||||
|         Joined, ///< The client is connected to the room and is ready to send/receive packets.
 |         Joined, ///< The client is connected to the room and is ready to send/receive packets.
 | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     enum class Error : u8 { | ||||||
|  |         // Reasons why connection was closed
 | ||||||
|         LostConnection, ///< Connection closed
 |         LostConnection, ///< Connection closed
 | ||||||
|  |         HostKicked,     ///< Kicked by the host
 | ||||||
| 
 | 
 | ||||||
|         // Reasons why connection was rejected
 |         // Reasons why connection was rejected
 | ||||||
|  |         UnknownError,       ///< Some error [permissions to network device missing or something]
 | ||||||
|         NameCollision,      ///< Somebody is already using this name
 |         NameCollision,      ///< Somebody is already using this name
 | ||||||
|         MacCollision,       ///< Somebody is already using that mac-address
 |         MacCollision,       ///< Somebody is already using that mac-address
 | ||||||
|         ConsoleIdCollision, ///< Somebody in the room has the same Console ID
 |         ConsoleIdCollision, ///< Somebody in the room has the same Console ID
 | ||||||
|         WrongVersion,       ///< The room version is not the same as for this RoomMember
 |         WrongVersion,       ///< The room version is not the same as for this RoomMember
 | ||||||
|         WrongPassword,      ///< The password doesn't match the one from the Room
 |         WrongPassword,      ///< The password doesn't match the one from the Room
 | ||||||
|         CouldNotConnect,    ///< The room is not responding to a connection attempt
 |         CouldNotConnect,    ///< The room is not responding to a connection attempt
 | ||||||
|         RoomIsFull          ///< Room is already at the maximum number of players
 |         RoomIsFull,         ///< Room is already at the maximum number of players
 | ||||||
|  |         HostBanned,         ///< The user is banned by the host
 | ||||||
|  | 
 | ||||||
|  |         // Reasons why moderation request failed
 | ||||||
|  |         PermissionDenied, ///< The user does not have mod permissions
 | ||||||
|  |         NoSuchUser,       ///< The nickname the user attempts to kick/ban does not exist
 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     struct MemberInformation { |     struct MemberInformation { | ||||||
|  | @ -161,6 +171,19 @@ public: | ||||||
|      */ |      */ | ||||||
|     void SendGameInfo(const GameInfo& game_info); |     void SendGameInfo(const GameInfo& game_info); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Sends a moderation request to the room. | ||||||
|  |      * @param type Moderation request type. | ||||||
|  |      * @param nickname The subject of the request. (i.e. the user you want to kick/ban) | ||||||
|  |      */ | ||||||
|  |     void SendModerationRequest(RoomMessageTypes type, const std::string& nickname); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Attempts to retrieve ban list from the room. | ||||||
|  |      * If success, the ban list callback would be called. Otherwise an error would be emitted. | ||||||
|  |      */ | ||||||
|  |     void RequestBanList(); | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Binds a function to an event that will be triggered every time the State of the member |      * Binds a function to an event that will be triggered every time the State of the member | ||||||
|      * changed. The function wil be called every time the event is triggered. The callback function |      * changed. The function wil be called every time the event is triggered. The callback function | ||||||
|  | @ -170,6 +193,15 @@ public: | ||||||
|      */ |      */ | ||||||
|     CallbackHandle<State> BindOnStateChanged(std::function<void(const State&)> callback); |     CallbackHandle<State> BindOnStateChanged(std::function<void(const State&)> callback); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Binds a function to an event that will be triggered every time an error happened. The | ||||||
|  |      * function wil be called every time the event is triggered. The callback function must not bind | ||||||
|  |      * or unbind a function. Doing so will cause a deadlock | ||||||
|  |      * @param callback The function to call | ||||||
|  |      * @return A handle used for removing the function from the registered list | ||||||
|  |      */ | ||||||
|  |     CallbackHandle<Error> BindOnError(std::function<void(const Error&)> callback); | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Binds a function to an event that will be triggered every time a WifiPacket is received. |      * Binds a function to an event that will be triggered every time a WifiPacket is received. | ||||||
|      * The function wil be called everytime the event is triggered. |      * The function wil be called everytime the event is triggered. | ||||||
|  | @ -210,6 +242,16 @@ public: | ||||||
|     CallbackHandle<StatusMessageEntry> BindOnStatusMessageReceived( |     CallbackHandle<StatusMessageEntry> BindOnStatusMessageReceived( | ||||||
|         std::function<void(const StatusMessageEntry&)> callback); |         std::function<void(const StatusMessageEntry&)> callback); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Binds a function to an event that will be triggered every time a requested ban list | ||||||
|  |      * received. The function will be called every time the event is triggered. The callback | ||||||
|  |      * function must not bind or unbind a function. Doing so will cause a deadlock | ||||||
|  |      * @param callback The function to call | ||||||
|  |      * @return A handle used for removing the function from the registered list | ||||||
|  |      */ | ||||||
|  |     CallbackHandle<Room::BanList> BindOnBanListReceived( | ||||||
|  |         std::function<void(const Room::BanList&)> callback); | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Leaves the current room. |      * Leaves the current room. | ||||||
|      */ |      */ | ||||||
|  | @ -224,24 +266,42 @@ static const char* GetStateStr(const RoomMember::State& s) { | ||||||
|     switch (s) { |     switch (s) { | ||||||
|     case RoomMember::State::Idle: |     case RoomMember::State::Idle: | ||||||
|         return "Idle"; |         return "Idle"; | ||||||
|     case RoomMember::State::Error: |  | ||||||
|         return "Error"; |  | ||||||
|     case RoomMember::State::Joining: |     case RoomMember::State::Joining: | ||||||
|         return "Joining"; |         return "Joining"; | ||||||
|     case RoomMember::State::Joined: |     case RoomMember::State::Joined: | ||||||
|         return "Joined"; |         return "Joined"; | ||||||
|     case RoomMember::State::LostConnection: |     } | ||||||
|  |     return "Unknown"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const char* GetErrorStr(const RoomMember::Error& e) { | ||||||
|  |     switch (e) { | ||||||
|  |     case RoomMember::Error::LostConnection: | ||||||
|         return "LostConnection"; |         return "LostConnection"; | ||||||
|     case RoomMember::State::NameCollision: |     case RoomMember::Error::HostKicked: | ||||||
|  |         return "HostKicked"; | ||||||
|  |     case RoomMember::Error::UnknownError: | ||||||
|  |         return "UnknownError"; | ||||||
|  |     case RoomMember::Error::NameCollision: | ||||||
|         return "NameCollision"; |         return "NameCollision"; | ||||||
|     case RoomMember::State::MacCollision: |     case RoomMember::Error::MacCollision: | ||||||
|         return "MacCollision"; |         return "MaxCollision"; | ||||||
|     case RoomMember::State::WrongVersion: |     case RoomMember::Error::ConsoleIdCollision: | ||||||
|  |         return "ConsoleIdCollision"; | ||||||
|  |     case RoomMember::Error::WrongVersion: | ||||||
|         return "WrongVersion"; |         return "WrongVersion"; | ||||||
|     case RoomMember::State::WrongPassword: |     case RoomMember::Error::WrongPassword: | ||||||
|         return "WrongPassword"; |         return "WrongPassword"; | ||||||
|     case RoomMember::State::CouldNotConnect: |     case RoomMember::Error::CouldNotConnect: | ||||||
|         return "CouldNotConnect"; |         return "CouldNotConnect"; | ||||||
|  |     case RoomMember::Error::RoomIsFull: | ||||||
|  |         return "RoomIsFull"; | ||||||
|  |     case RoomMember::Error::HostBanned: | ||||||
|  |         return "HostBanned"; | ||||||
|  |     case RoomMember::Error::PermissionDenied: | ||||||
|  |         return "PermissionDenied"; | ||||||
|  |     case RoomMember::Error::NoSuchUser: | ||||||
|  |         return "NoSuchUser"; | ||||||
|     } |     } | ||||||
|     return "Unknown"; |     return "Unknown"; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue