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
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue