Skip to content

feat(Core): Add voice chat implementation. #22152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conf/dist/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ option(WITHOUT_GIT "Disable the GIT testing routines"
option(ENABLE_VMAP_CHECKS "Enable Checks relative to DisableMgr system on vmap" 1)
option(WITH_DYNAMIC_LINKING "Enable dynamic library linking." 0)
option(WITH_STRICT_DATABASE_TYPE_CHECKS "Enable strict checking of database field value accessors" 0)
option(BUILD_VOICECHAT "Build voicechat server and handlers" 0)
option(WITHOUT_METRICS "Disable metrics reporting (i.e. InfluxDB and Grafana)" 0)
option(WITH_DETAILED_METRICS "Enable detailed metrics reporting (i.e. time each session takes to update)" 0)

Expand Down
30 changes: 30 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,33 @@ add_subdirectory(server)
if (TOOLS_BUILD AND NOT TOOLS_BUILD STREQUAL "none")
add_subdirectory(tools)
endif()

# Voice Chat server and handlers
if(BUILD_VOICECHAT)
include(FetchContent)

FetchContent_Declare(
voicechat-server
GIT_REPOSITORY "https://github.com/celguar/voicechat-server.git"
GIT_TAG "main"
)

if(NOT voicechat-server_POPULATED)
message(STATUS "Fetching VoiceChat server...")

FetchContent_Populate(voicechat-server)

if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/voicechat-server)
file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/voicechat-server)
endif()

file(COPY ${voicechat-server_SOURCE_DIR}/. DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/voicechat-server)
message(STATUS "VoiceChat Server fetched and populated in ${CMAKE_CURRENT_SOURCE_DIR}/voicechat-server")
endif()

add_subdirectory(voicechat-server)
else()
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/voicechat-server)
file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/voicechat-server)
endif()
endif()
6 changes: 6 additions & 0 deletions src/cmake/showoptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ if(WITH_STRICT_DATABASE_TYPE_CHECKS)
add_definitions(-DACORE_STRICT_DATABASE_TYPE_CHECKS)
endif()

if(BUILD_VOICECHAT)
message("* Build VoiceChat : Yes")
else()
message("* Build VoiceChat : No (Default)")
endif()

if(WITHOUT_METRICS)
message("")
message(" *** WITHOUT_METRICS - WARNING!")
Expand Down
28 changes: 28 additions & 0 deletions src/server/apps/worldserver/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "SecretMgr.h"
#include "SharedDefines.h"
#include "SteadyTimer.h"
#include "VoiceChat/VoiceChatMgr.h"
#include "World.h"
#include "WorldSessionMgr.h"
#include "WorldSocket.h"
Expand All @@ -60,6 +61,8 @@
#include <openssl/crypto.h>
#include <openssl/opensslv.h>

// #include "VoiceChatMgr.h"

#if AC_PLATFORM == AC_PLATFORM_WINDOWS
#include "ServiceWin32.h"
char serviceName[] = "worldserver";
Expand Down Expand Up @@ -317,6 +320,9 @@ int main(int argc, char** argv)
sScriptMgr->OnAfterUnloadAllMaps();
});

// initialize VoiceChatMgr with the same ioContext
sVoiceChatMgr.Init(*ioContext);

// Start the Remote Access port (acceptor) if enabled
std::unique_ptr<AsyncAcceptor> raAcceptor;
if (sConfigMgr->GetOption<bool>("Ra.Enable", false))
Expand Down Expand Up @@ -367,6 +373,28 @@ int main(int argc, char** argv)
ClearOnlineAccounts();
});

// std::shared_ptr<void> sVoiceChatSocketMgrHandle(nullptr, [](void*)
// {
// if (sVoiceChatMgr.CanUseVoiceChat())
// sVoiceChatMgr.SocketDisconnected(); // close voice socket and remove channels
// LOG_ERROR("server.worldserver", "VOICE CHAT SOCKET STOPNETWORK MAIN.CPP");
// sVoiceChatSocketMgr.StopNetwork();
// });

// if (!sVoiceChatSocketMgr.StartNetwork(*ioContext, "127.0.0.1", 3725, 1))
// {
// LOG_ERROR("server.worldserver", "Failed to initialize network");
// World::StopNow(ERROR_EXIT_CODE);
// return 1;
// }
// else
// {
// for (int i = 0; i < 50; ++i)
// {
// LOG_INFO("sql.sql", "Started voice server network!");
// }
// }

// Set server online (allow connecting now)
LoginDatabase.DirectExecute("UPDATE realmlist SET flag = flag & ~{}, population = 0 WHERE id = '{}'", REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);
realm.PopulationLevel = 0.0f;
Expand Down
42 changes: 42 additions & 0 deletions src/server/apps/worldserver/worldserver.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -4548,6 +4548,48 @@ Respawn.DynamicMinimumGameObject = 10
#
###################################################################################################

###################################################################################################################
# VOICE CHAT CONFIG
#
# VoiceChat.Enabled
# Enable Voice Chat
# Default: 0 - off
# 1 - on
#
# VoiceChat.ServerPort
# TCP port that world server should use to connect to voice chat server
# Default: 3725
#
# VoiceChat.ServerAddress
# IP that world server should use to connect to voice chat server
# Default: 127.0.0.1
#
# VoiceChat.VoicePort
# UDP port that game client should use to connect to voice chat server, should be available for client
# Default: 3724
#
# VoiceChat.VoiceAddress
# IP that game client should use to connect to voice chat server, should be available for client
# Default: 127.0.0.1
#
# VoiceChat.MaxConnectAttempts
# Maximum attempts to connect/reconnect to voice chat server
# Default: -1 (infinite)
# 0 (disabled)
# 1+ (limited attempts)
#
###################################################################################################################

VoiceChat.Enabled = 0
VoiceChat.ServerPort = 3725
VoiceChat.ServerAddress = 127.0.0.1
VoiceChat.VoicePort = 3724
VoiceChat.VoiceAddress = 127.0.0.1
VoiceChat.MaxConnectAttempts = -1

#
###################################################################################################

###################################################################################################
# #
# GAME SETTINGS END #
Expand Down
103 changes: 103 additions & 0 deletions src/server/game/Chat/Channels/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "SocialMgr.h"
#include "VoiceChat/VoiceChatMgr.h"
#include "World.h"

Channel::Channel(std::string const& name, uint32 channelId, uint32 channelDBId, TeamId teamId, bool announce, bool ownership):
Expand Down Expand Up @@ -212,6 +213,23 @@ void Channel::JoinChannel(Player* player, std::string const& pass)
if (_channelRights.joinMessage.length())
ChatHandler(player->GetSession()).PSendSysMessage("{}", _channelRights.joinMessage);

// join voice chat
if (!IsConstant() && HasFlag(CHANNEL_FLAG_CUSTOM) && sVoiceChatMgr.CanUseVoiceChat())
{
// first voice chat enabled member turns it on
// only proof is https://www.youtube.com/watch?v=h5oH4ER2cJ0 where voice chat is auto enabled on new channel
if (!IsVoiceEnabled())
{
if (player->GetSession()->IsVoiceChatEnabled())
{
// toggle voice and update player flags
ToggleVoice(player);
}
}
if (IsVoiceEnabled())
sVoiceChatMgr.AddToCustomVoiceChatChannel(guid, this->GetName(), player->GetTeamId());
}

WorldPacket data;
MakeYouJoined(&data);
SendToOne(&data, guid);
Expand Down Expand Up @@ -310,6 +328,10 @@ void Channel::LeaveChannel(Player* player, bool send)
SetOwner(ObjectGuid::Empty);
}
}

// leave voice chat
if (IsVoiceEnabled())
sVoiceChatMgr.RemoveFromCustomVoiceChatChannel(guid, this->GetName(), player->GetTeamId());
}

void Channel::KickOrBan(Player const* player, std::string const& badname, bool ban)
Expand Down Expand Up @@ -685,6 +707,87 @@ void Channel::SendWhoOwner(ObjectGuid guid)
SendToOne(&data, guid);
}

void Channel::AddVoiceChatMembersAfterCreate()
{
// add voice enabled players to channel after it's created on voice server
for (auto const& playerStore : playersStore)
if (playerStore.second.plrPtr->GetSession()->IsVoiceChatEnabled())
sVoiceChatMgr.AddToCustomVoiceChatChannel(playerStore.second.plrPtr->GetGUID(), this->GetName(), playerStore.second.plrPtr->GetTeamId());
}

void Channel::ToggleVoice(Player* player)
{
// silently disable if voice server disconnected
if (!player)
{
m_voice = !m_voice;
if (m_voice)
_flags |= CHANNEL_FLAG_VOICE;
else
_flags &= ~CHANNEL_FLAG_VOICE;

return;
}

ObjectGuid guid = player->GetGUID();

if (!IsOn(guid))
{
WorldPacket data;
MakeNotMember(&data);
SendToOne(&data, guid);
return;
}

// const uint32 level = sWorld->getConfig(CONFIG_UINT32_GM_LEVEL_CHANNEL_MODERATION);
// const bool gm = (level && player->GetSession()->GetSecurity() >= level);
const bool gm = false;

if (!playersStore[guid].IsOwner() && !playersStore[guid].IsOwnerGM())
{
WorldPacket data;
MakeNotOwner(&data);
SendToOne(&data, guid);
return;
}

// toggle channel voice
m_voice = !m_voice;

WorldPacket data;
if (m_voice)
MakeVoiceOn(&data, guid);
else
MakeVoiceOff(&data ,guid);

SendToAll(&data);

if (m_voice)
_flags |= CHANNEL_FLAG_VOICE;
else
_flags &= ~CHANNEL_FLAG_VOICE;

// update player flags, maybe used in right click menu in chat UI
for (auto const& playerStore : playersStore)
{
if (Player* member = playerStore.second.plrPtr)
{
if (WorldSession* session = member->GetSession())
{
if (session->IsVoiceChatEnabled())
{
playersStore[playerStore.first].SetVoiced(m_voice);
}
}
}
}

if (m_voice)
{
sVoiceChatMgr.AddToCustomVoiceChatChannel(guid, this->GetName(), player->GetTeamId());
}
}

void Channel::List(Player const* player)
{
ObjectGuid guid = player->GetGUID();
Expand Down
24 changes: 21 additions & 3 deletions src/server/game/Chat/Channels/Channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,18 @@ class Channel
if (state) flags |= MEMBER_FLAG_MUTED;
else flags &= ~MEMBER_FLAG_MUTED;
}
[[nodiscard]] bool IsMicMuted() const { return flags & MEMBER_FLAG_MIC_MUTED; }
void SetMicMuted(bool state)
{
if (state) flags |= MEMBER_FLAG_MIC_MUTED;
else flags &= ~MEMBER_FLAG_MIC_MUTED;
}
[[nodiscard]] bool IsVoiced() const { return flags & MEMBER_FLAG_VOICED; }
void SetVoiced(bool state)
{
if (state) flags |= MEMBER_FLAG_VOICED;
else flags &= ~MEMBER_FLAG_VOICED;
}
private:
bool _gmStatus = false;
};
Expand Down Expand Up @@ -205,6 +217,8 @@ class Channel
void UnsetModerator(Player const* player, std::string const& newname) { SetMode(player, newname, true, false); }
void SetMute(Player const* player, std::string const& newname) { SetMode(player, newname, false, true); }
void UnsetMute(Player const* player, std::string const& newname) { SetMode(player, newname, false, false); }
// inline void SetMicMute(Player* player, const char* targetName, bool set) { SetModeFlags(player, targetName, MEMBER_FLAG_MIC_MUTED, set); }
// inline void SetVoiced(Player* player, const char* targetName, bool set) { SetModeFlags(player, targetName, MEMBER_FLAG_VOICED, set); } // Not used
void List(Player const* player);
void Announce(Player const* player);
void Say(ObjectGuid guid, std::string const& what, uint32 lang);
Expand All @@ -217,10 +231,16 @@ class Channel
static void CleanOldChannelsInDB();
void ToggleModeration(Player* p);

[[nodiscard]] bool IsOn(ObjectGuid who) const { return playersStore.find(who) != playersStore.end(); }
[[nodiscard]] bool IsBanned(ObjectGuid guid) const;

// pussywizard:
void AddWatching(Player* p);
void RemoveWatching(Player* p);

bool IsVoiceEnabled() const { return HasFlag(CHANNEL_FLAG_VOICE); }
void ToggleVoice(Player* player = nullptr);
void AddVoiceChatMembersAfterCreate();
private:
// initial packet data (notify type and channel name)
void MakeNotifyPacket(WorldPacket* data, uint8 notify_type);
Expand Down Expand Up @@ -269,9 +289,6 @@ class Channel

bool ShouldAnnouncePlayer(Player const* player) const;

[[nodiscard]] bool IsOn(ObjectGuid who) const { return playersStore.find(who) != playersStore.end(); }
[[nodiscard]] bool IsBanned(ObjectGuid guid) const;

void UpdateChannelInDB() const;
void UpdateChannelUseageInDB() const;
void AddChannelBanToDB(ObjectGuid guid, uint32 time) const;
Expand Down Expand Up @@ -329,6 +346,7 @@ class Channel
ObjectGuid _ownerGUID;
std::string _name;
std::string _password;
bool m_voice = false;
ChannelRights _channelRights;
PlayerContainer playersStore;
BannedContainer bannedStore;
Expand Down
5 changes: 4 additions & 1 deletion src/server/game/Chat/Channels/ChannelMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "Player.h"
#include "StringConvert.h"
#include "Tokenize.h"
#include "VoiceChatMgr.h"
#include "World.h"

ChannelMgr::~ChannelMgr()
Expand Down Expand Up @@ -60,7 +61,7 @@ void ChannelMgr::LoadChannels()
return;
}

std::vector<std::pair<std::string, uint32>> toDelete;
std::vector<std::pair<std::string, TeamId>> toDelete;
do
{
Field* fields = result->Fetch();
Expand Down Expand Up @@ -108,6 +109,8 @@ void ChannelMgr::LoadChannels()

for (auto& pair : toDelete)
{
sVoiceChatMgr.DeleteCustomVoiceChatChannel(pair.first, pair.second);

CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHANNEL);
stmt->SetData(0, pair.first);
stmt->SetData(1, pair.second);
Expand Down
5 changes: 5 additions & 0 deletions src/server/game/Entities/Player/SocialMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ bool PlayerSocial::HasIgnore(ObjectGuid ignore_guid) const
return _checkContact(ignore_guid, SOCIAL_FLAG_IGNORED);
}

bool PlayerSocial::HasMute(ObjectGuid ignore_guid) const
{
return _checkContact(ignore_guid, SOCIAL_FLAG_MUTED);
}

SocialMgr::SocialMgr()
{
}
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Entities/Player/SocialMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class PlayerSocial
// Misc
bool HasFriend(ObjectGuid friend_guid) const;
bool HasIgnore(ObjectGuid ignore_guid) const;
bool HasMute(ObjectGuid ignore_guid) const;
ObjectGuid GetPlayerGUID() const { return m_playerGUID; }
void SetPlayerGUID(ObjectGuid guid) { m_playerGUID = guid; }
uint32 GetNumberOfSocialsWithFlag(SocialFlag flag) const;
Expand Down
Loading