commit
f3d5afb83b
@ -112,6 +112,7 @@ namespace Components
|
|||||||
Loader::Register(new Ceg());
|
Loader::Register(new Ceg());
|
||||||
Loader::Register(new UserInfo());
|
Loader::Register(new UserInfo());
|
||||||
Loader::Register(new Events());
|
Loader::Register(new Events());
|
||||||
|
Loader::Register(new Voice());
|
||||||
|
|
||||||
Loader::Register(new GSC());
|
Loader::Register(new GSC());
|
||||||
|
|
||||||
|
@ -143,5 +143,6 @@ namespace Components
|
|||||||
#include "Modules/Ceg.hpp"
|
#include "Modules/Ceg.hpp"
|
||||||
#include "Modules/UserInfo.hpp"
|
#include "Modules/UserInfo.hpp"
|
||||||
#include "Modules/Events.hpp"
|
#include "Modules/Events.hpp"
|
||||||
|
#include "Modules/Voice.hpp"
|
||||||
|
|
||||||
#include "Modules/GSC/GSC.hpp"
|
#include "Modules/GSC/GSC.hpp"
|
||||||
|
@ -130,7 +130,7 @@ namespace Components
|
|||||||
|
|
||||||
// Parse proto data
|
// Parse proto data
|
||||||
Proto::Auth::Connect connectData;
|
Proto::Auth::Connect connectData;
|
||||||
if (msg->cursize <= 12 || !connectData.ParseFromString(std::string(&msg->data[12], msg->cursize - 12)))
|
if (msg->cursize <= 12 || !connectData.ParseFromString(std::string(reinterpret_cast<char*>(&msg->data[12]), msg->cursize - 12)))
|
||||||
{
|
{
|
||||||
Network::Send(address, "error\nInvalid connect packet!");
|
Network::Send(address, "error\nInvalid connect packet!");
|
||||||
return;
|
return;
|
||||||
|
@ -28,8 +28,6 @@ namespace Components
|
|||||||
|
|
||||||
static void Dvar_InfoString_Stub(char* s, const char* key, const char* value);
|
static void Dvar_InfoString_Stub(char* s, const char* key, const char* value);
|
||||||
|
|
||||||
static void SetCachedPlayerData(int clientNum);
|
|
||||||
|
|
||||||
static void ClientUserinfoChanged(const char* s, int clientNum);
|
static void ClientUserinfoChanged(const char* s, int clientNum);
|
||||||
static void ClientUserinfoChanged_Stub();
|
static void ClientUserinfoChanged_Stub();
|
||||||
|
|
||||||
|
@ -568,6 +568,8 @@ namespace Components
|
|||||||
|
|
||||||
Console::Console()
|
Console::Console()
|
||||||
{
|
{
|
||||||
|
AssertOffset(Game::clientUIActive_t, connectionState, 0x9B8);
|
||||||
|
|
||||||
// Console '%s: %s> ' string
|
// Console '%s: %s> ' string
|
||||||
Utils::Hook::Set<const char*>(0x5A44B4, "IW4x MP: " VERSION "> ");
|
Utils::Hook::Set<const char*>(0x5A44B4, "IW4x MP: " VERSION "> ");
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ namespace Components
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string data(message->data + offset, message->cursize - offset);
|
const std::string data(reinterpret_cast<char*>(message->data) + offset, message->cursize - offset);
|
||||||
|
|
||||||
Address address_ = address;
|
Address address_ = address;
|
||||||
handler->second(address_, data);
|
handler->second(address_, data);
|
||||||
@ -370,6 +370,8 @@ namespace Components
|
|||||||
Utils::Hook::Set<BYTE>(0x5AA5B6, 0xEB); // CL_SteamServerAuth
|
Utils::Hook::Set<BYTE>(0x5AA5B6, 0xEB); // CL_SteamServerAuth
|
||||||
Utils::Hook::Set<BYTE>(0x5AA69F, 0xEB); // echo
|
Utils::Hook::Set<BYTE>(0x5AA69F, 0xEB); // echo
|
||||||
Utils::Hook::Set<BYTE>(0x5AAA82, 0xEB); // SP
|
Utils::Hook::Set<BYTE>(0x5AAA82, 0xEB); // SP
|
||||||
|
Utils::Hook::Set<BYTE>(0x5A9F18, 0xEB); // CL_VoiceConnectionTestPacket
|
||||||
|
Utils::Hook::Set<BYTE>(0x5A9FF3, 0xEB); // CL_HandleRelayPacket
|
||||||
|
|
||||||
Network::OnPacket("resolveAddress", [](const Address& address, [[maybe_unused]] const std::string& data)
|
Network::OnPacket("resolveAddress", [](const Address& address, [[maybe_unused]] const std::string& data)
|
||||||
{
|
{
|
||||||
|
@ -102,8 +102,8 @@ namespace Components
|
|||||||
|
|
||||||
void Security::NET_DeferPacketToClientStub(Game::netadr_t* net_from, Game::msg_t* net_message)
|
void Security::NET_DeferPacketToClientStub(Game::netadr_t* net_from, Game::msg_t* net_message)
|
||||||
{
|
{
|
||||||
assert(net_from != nullptr);
|
assert(net_from);
|
||||||
assert(net_message != nullptr);
|
assert(net_message);
|
||||||
|
|
||||||
if (static_cast<std::size_t>(net_message->cursize) >= sizeof(Game::DeferredMsg::data))
|
if (static_cast<std::size_t>(net_message->cursize) >= sizeof(Game::DeferredMsg::data))
|
||||||
{
|
{
|
||||||
|
@ -24,10 +24,8 @@ namespace Components
|
|||||||
Game::Com_Printf(0, "Sending stat packet %i to server.\n", i);
|
Game::Com_Printf(0, "Sending stat packet %i to server.\n", i);
|
||||||
|
|
||||||
// alloc
|
// alloc
|
||||||
Game::msg_t msg;
|
Game::msg_t msg{};
|
||||||
char buffer[2048];
|
unsigned char buffer[2048]{};
|
||||||
ZeroMemory(&msg, sizeof(msg));
|
|
||||||
ZeroMemory(&buffer, sizeof(buffer));
|
|
||||||
|
|
||||||
// init
|
// init
|
||||||
Game::MSG_Init(&msg, buffer, sizeof(buffer));
|
Game::MSG_Init(&msg, buffer, sizeof(buffer));
|
||||||
@ -53,7 +51,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send statpacket
|
// send statpacket
|
||||||
Network::SendRaw(Game::NS_CLIENT1, *reinterpret_cast<Game::netadr_t*>(0xA1E888), std::string(msg.data, msg.cursize));
|
Network::SendRaw(Game::NS_CLIENT1, *reinterpret_cast<Game::netadr_t*>(0xA1E888), std::string(reinterpret_cast<char*>(msg.data), msg.cursize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ namespace Components
|
|||||||
|
|
||||||
void Theatre::WriteBaseline()
|
void Theatre::WriteBaseline()
|
||||||
{
|
{
|
||||||
static char bufData[131072];
|
static unsigned char bufData[131072];
|
||||||
static char cmpData[131072];
|
static char cmpData[131072];
|
||||||
|
|
||||||
Game::msg_t buf;
|
Game::msg_t buf;
|
||||||
@ -56,7 +56,7 @@ namespace Components
|
|||||||
Game::MSG_WriteData(&buf, &Theatre::BaselineSnapshot[Theatre::BaselineSnapshotMsgOff], Theatre::BaselineSnapshotMsgLen - Theatre::BaselineSnapshotMsgOff);
|
Game::MSG_WriteData(&buf, &Theatre::BaselineSnapshot[Theatre::BaselineSnapshotMsgOff], Theatre::BaselineSnapshotMsgLen - Theatre::BaselineSnapshotMsgOff);
|
||||||
Game::MSG_WriteByte(&buf, 6);
|
Game::MSG_WriteByte(&buf, 6);
|
||||||
|
|
||||||
int compressedSize = Game::MSG_WriteBitsCompress(false, buf.data, cmpData, buf.cursize);
|
int compressedSize = Game::MSG_WriteBitsCompress(false, reinterpret_cast<char*>(buf.data), cmpData, buf.cursize);
|
||||||
int fileCompressedSize = compressedSize + 4;
|
int fileCompressedSize = compressedSize + 4;
|
||||||
|
|
||||||
int byte8 = 8;
|
int byte8 = 8;
|
||||||
|
365
src/Components/Modules/Voice.cpp
Normal file
365
src/Components/Modules/Voice.cpp
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
#include <STDInclude.hpp>
|
||||||
|
|
||||||
|
namespace Components
|
||||||
|
{
|
||||||
|
Game::VoicePacket_t Voice::voicePackets[Game::MAX_CLIENTS][MAX_SERVER_QUEUED_VOICE_PACKETS];
|
||||||
|
int Voice::voicePacketCount[Game::MAX_CLIENTS];
|
||||||
|
|
||||||
|
bool Voice::s_playerMute[Game::MAX_CLIENTS];
|
||||||
|
|
||||||
|
const Game::dvar_t* Voice::sv_voice;
|
||||||
|
|
||||||
|
bool Voice::SV_VoiceEnabled()
|
||||||
|
{
|
||||||
|
return sv_voice->current.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::SV_WriteVoiceDataToClient(const int clientNum, Game::msg_t* msg)
|
||||||
|
{
|
||||||
|
assert(voicePacketCount[clientNum] >= 0);
|
||||||
|
assert(voicePacketCount[clientNum] <= MAX_SERVER_QUEUED_VOICE_PACKETS);
|
||||||
|
|
||||||
|
Game::MSG_WriteByte(msg, voicePacketCount[clientNum]);
|
||||||
|
for (auto packet = 0; packet < voicePacketCount[clientNum]; ++packet)
|
||||||
|
{
|
||||||
|
Game::MSG_WriteByte(msg, voicePackets[clientNum][packet].talker);
|
||||||
|
|
||||||
|
assert(voicePackets[clientNum][packet].dataSize < (2 << 15));
|
||||||
|
|
||||||
|
Game::MSG_WriteByte(msg, voicePackets[clientNum][packet].dataSize);
|
||||||
|
Game::MSG_WriteData(msg, voicePackets[clientNum][packet].data, voicePackets[clientNum][packet].dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!msg->overflowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::SV_SendClientVoiceData(Game::client_t* client)
|
||||||
|
{
|
||||||
|
const auto msg_buf = std::make_unique<unsigned char[]>(0x10000);
|
||||||
|
Game::msg_t msg{};
|
||||||
|
const auto clientNum = client - Game::svs_clients;
|
||||||
|
|
||||||
|
assert(voicePacketCount[clientNum] >= 0);
|
||||||
|
|
||||||
|
if (client->state == Game::CS_ACTIVE && voicePacketCount[clientNum])
|
||||||
|
{
|
||||||
|
Game::MSG_Init(&msg, msg_buf.get(), 0x10000);
|
||||||
|
|
||||||
|
assert(msg.cursize == 0);
|
||||||
|
assert(msg.bit == 0);
|
||||||
|
|
||||||
|
Game::MSG_WriteString(&msg, "v");
|
||||||
|
SV_WriteVoiceDataToClient(clientNum, &msg);
|
||||||
|
|
||||||
|
if (msg.overflowed)
|
||||||
|
{
|
||||||
|
Logger::Warning(Game::CON_CHANNEL_SERVER, "WARNING: voice msg overflowed for {}\n", client->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Game::NET_OutOfBandVoiceData(Game::NS_SERVER, client->netchan.remoteAddress, msg.data, msg.cursize, true);
|
||||||
|
voicePacketCount[clientNum] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::SV_SendClientMessages_Stub(Game::client_t* client, Game::msg_t* msg, unsigned char* snapshotMsgBuf)
|
||||||
|
{
|
||||||
|
// SV_EndClientSnapshot
|
||||||
|
Utils::Hook::Call<void(Game::client_t*, Game::msg_t*, unsigned char*)>(0x4F5300)(client, msg, snapshotMsgBuf);
|
||||||
|
|
||||||
|
SV_SendClientVoiceData(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Voice::OnSameTeam(Game::gentity_s* ent1, Game::gentity_s* ent2)
|
||||||
|
{
|
||||||
|
if (!ent1->client || !ent2->client)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ent1->client->sess.cs.team)
|
||||||
|
{
|
||||||
|
return ent1->client->sess.cs.team == ent2->client->sess.cs.team;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::SV_QueueVoicePacket(const int talkerNum, const int clientNum, Game::VoicePacket_t* voicePacket)
|
||||||
|
{
|
||||||
|
assert(talkerNum >= 0);
|
||||||
|
assert(clientNum >= 0);
|
||||||
|
assert(talkerNum < (*Game::sv_maxclients)->current.integer);
|
||||||
|
assert(clientNum < (*Game::sv_maxclients)->current.integer);
|
||||||
|
|
||||||
|
if (voicePacketCount[clientNum] < MAX_SERVER_QUEUED_VOICE_PACKETS)
|
||||||
|
{
|
||||||
|
voicePackets[clientNum][voicePacketCount[clientNum]].dataSize = voicePacket->dataSize;
|
||||||
|
std::memcpy(voicePackets[clientNum][voicePacketCount[clientNum]].data, voicePacket->data, voicePacket->dataSize);
|
||||||
|
|
||||||
|
assert(talkerNum == static_cast<byte>(talkerNum));
|
||||||
|
voicePackets[clientNum][voicePacketCount[clientNum]].talker = static_cast<char>(talkerNum);
|
||||||
|
++voicePacketCount[clientNum];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::G_BroadcastVoice(Game::gentity_s* talker, Game::VoicePacket_t* voicePacket)
|
||||||
|
{
|
||||||
|
for (auto otherPlayer = 0; otherPlayer < (*Game::sv_maxclients)->current.integer; ++otherPlayer)
|
||||||
|
{
|
||||||
|
auto* ent = &Game::g_entities[otherPlayer];
|
||||||
|
auto* client = ent->client;
|
||||||
|
|
||||||
|
if (ent->r.isInUse && client && (client->sess.sessionState == Game::SESS_STATE_INTERMISSION || OnSameTeam(talker, ent) || talker->client->sess.cs.team == Game::TEAM_FREE) &&
|
||||||
|
(ent->client->sess.sessionState == talker->client->sess.sessionState || (ent->client->sess.sessionState == Game::SESS_STATE_DEAD || talker->client->sess.sessionState == Game::SESS_STATE_DEAD) &&
|
||||||
|
(*Game::g_deadChat)->current.enabled) && (talker != ent))
|
||||||
|
{
|
||||||
|
SV_QueueVoicePacket(talker->s.number, otherPlayer, voicePacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::SV_UserVoice(Game::client_t* cl, Game::msg_t* msg)
|
||||||
|
{
|
||||||
|
Game::VoicePacket_t voicePacket{};
|
||||||
|
|
||||||
|
if (!SV_VoiceEnabled())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto packetCount = Game::MSG_ReadByte(msg);
|
||||||
|
|
||||||
|
assert(cl->gentity);
|
||||||
|
|
||||||
|
for (auto packet = 0; packet < packetCount; ++packet)
|
||||||
|
{
|
||||||
|
voicePacket.dataSize = Game::MSG_ReadByte(msg);
|
||||||
|
if (voicePacket.dataSize <= 0 || voicePacket.dataSize > MAX_VOICE_PACKET_DATA)
|
||||||
|
{
|
||||||
|
Logger::Print(Game::CON_CHANNEL_SERVER, "Received invalid voice packet of size {} from {}\n", voicePacket.dataSize, cl->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(voicePacket.dataSize <= MAX_VOICE_PACKET_DATA);
|
||||||
|
assert(msg->data);
|
||||||
|
assert(voicePacket.data);
|
||||||
|
|
||||||
|
Game::MSG_ReadData(msg, voicePacket.data, voicePacket.dataSize);
|
||||||
|
G_BroadcastVoice(cl->gentity, &voicePacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::SV_PreGameUserVoice(Game::client_t* cl, Game::msg_t* msg)
|
||||||
|
{
|
||||||
|
Game::VoicePacket_t voicePacket{};
|
||||||
|
|
||||||
|
if (!SV_VoiceEnabled())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto talker = cl - Game::svs_clients;
|
||||||
|
|
||||||
|
AssertIn(talker, (*Game::sv_maxclients)->current.integer);
|
||||||
|
|
||||||
|
const auto packetCount = Game::MSG_ReadByte(msg);
|
||||||
|
for (auto packet = 0; packet < packetCount; ++packet)
|
||||||
|
{
|
||||||
|
voicePacket.dataSize = Game::MSG_ReadShort(msg);
|
||||||
|
if (voicePacket.dataSize <= 0 || voicePacket.dataSize > MAX_VOICE_PACKET_DATA)
|
||||||
|
{
|
||||||
|
Logger::Print(Game::CON_CHANNEL_SERVER, "Received invalid voice packet of size {} from {}\n", voicePacket.dataSize, cl->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(voicePacket.dataSize <= MAX_VOICE_PACKET_DATA);
|
||||||
|
assert(msg->data);
|
||||||
|
assert(voicePacket.data);
|
||||||
|
|
||||||
|
Game::MSG_ReadData(msg, voicePacket.data, voicePacket.dataSize);
|
||||||
|
for (auto otherPlayer = 0; otherPlayer < (*Game::sv_maxclients)->current.integer; ++otherPlayer)
|
||||||
|
{
|
||||||
|
if (otherPlayer != talker && Game::svs_clients[otherPlayer].state >= Game::CS_CONNECTED)
|
||||||
|
{
|
||||||
|
SV_QueueVoicePacket(talker, otherPlayer, &voicePacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::SV_VoicePacket(Game::netadr_t from, Game::msg_t* msg)
|
||||||
|
{
|
||||||
|
auto qport = Game::MSG_ReadShort(msg);
|
||||||
|
auto* cl = Game::SV_FindClientByAddress(from, qport, 0);
|
||||||
|
if (!cl || cl->state == Game::CS_ZOMBIE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl->lastPacketTime = *Game::svs_time;
|
||||||
|
if (cl->state < Game::CS_ACTIVE)
|
||||||
|
{
|
||||||
|
SV_PreGameUserVoice(cl, msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(cl->gentity);
|
||||||
|
SV_UserVoice(cl, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::CL_WriteVoicePacket_Hk(const int localClientNum)
|
||||||
|
{
|
||||||
|
const auto connstate = Game::CL_GetLocalClientConnectionState(localClientNum);
|
||||||
|
const auto clc = Game::CL_GetLocalClientConnection(localClientNum);
|
||||||
|
const auto* vc = Game::CL_GetLocalClientVoiceCommunication(localClientNum);
|
||||||
|
if (clc->demoplaying || (connstate < Game::CA_LOADING))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char voicePacketBuf[0x800]{};
|
||||||
|
Game::msg_t msg{};
|
||||||
|
|
||||||
|
Game::MSG_Init(&msg, voicePacketBuf, sizeof(voicePacketBuf));
|
||||||
|
Game::MSG_WriteString(&msg, "v");
|
||||||
|
Game::MSG_WriteShort(&msg, clc->qport);
|
||||||
|
Game::MSG_WriteByte(&msg, vc->voicePacketCount);
|
||||||
|
|
||||||
|
for (auto voicePacket = 0; voicePacket < vc->voicePacketCount; ++voicePacket)
|
||||||
|
{
|
||||||
|
assert(vc->voicePackets[voicePacket].dataSize > 0);
|
||||||
|
assert(vc->voicePackets[voicePacket].dataSize < (2 << 15));
|
||||||
|
|
||||||
|
Game::MSG_WriteByte(&msg, vc->voicePackets[voicePacket].dataSize);
|
||||||
|
Game::MSG_WriteData(&msg, vc->voicePackets[voicePacket].data, vc->voicePackets[voicePacket].dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::NET_OutOfBandVoiceData(clc->netchan.sock, clc->serverAddress, msg.data, msg.cursize, true);
|
||||||
|
if ((*Game::cl_showSend)->current.enabled)
|
||||||
|
{
|
||||||
|
Logger::Print(Game::CON_CHANNEL_CLIENT, "voice: {}\n", msg.cursize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Voice::CL_IsPlayerMuted_Hk([[maybe_unused]] Game::SessionData* session, [[maybe_unused]] const int localClientNum, const int muteClientIndex)
|
||||||
|
{
|
||||||
|
AssertIn(muteClientIndex, Game::MAX_CLIENTS);
|
||||||
|
return s_playerMute[muteClientIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::CL_MutePlayer_Hk([[maybe_unused]] Game::SessionData* session, const int muteClientIndex)
|
||||||
|
{
|
||||||
|
AssertIn(muteClientIndex, Game::MAX_CLIENTS);
|
||||||
|
s_playerMute[muteClientIndex] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::Voice_UnmuteMember_Hk([[maybe_unused]] Game::SessionData* session, const int clientNum)
|
||||||
|
{
|
||||||
|
AssertIn(clientNum, Game::MAX_CLIENTS);
|
||||||
|
s_playerMute[clientNum] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::CL_TogglePlayerMute(const int localClientNum, const int muteClientIndex)
|
||||||
|
{
|
||||||
|
AssertIn(muteClientIndex, Game::MAX_CLIENTS);
|
||||||
|
|
||||||
|
if (CL_IsPlayerMuted_Hk(nullptr, localClientNum, muteClientIndex))
|
||||||
|
{
|
||||||
|
Voice_UnmuteMember_Hk(nullptr, muteClientIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CL_MutePlayer_Hk(nullptr, muteClientIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::CL_VoicePacket_Hk(const int localClientNum, Game::msg_t* msg)
|
||||||
|
{
|
||||||
|
const auto numPackets = Game::MSG_ReadByte(msg);
|
||||||
|
if (numPackets < 0 || numPackets > MAX_SERVER_QUEUED_VOICE_PACKETS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::VoicePacket_t voicePacket{};
|
||||||
|
for (auto packet = 0; packet < numPackets; ++packet)
|
||||||
|
{
|
||||||
|
voicePacket.talker = static_cast<char>(Game::MSG_ReadByte(msg));
|
||||||
|
voicePacket.dataSize = Game::MSG_ReadByte(msg);
|
||||||
|
if (voicePacket.dataSize <= 0 || voicePacket.dataSize > MAX_VOICE_PACKET_DATA)
|
||||||
|
{
|
||||||
|
Logger::Print(Game::CON_CHANNEL_CLIENT, "Invalid server voice packet of {} bytes\n", voicePacket.dataSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::MSG_ReadData(msg, voicePacket.data, voicePacket.dataSize);
|
||||||
|
|
||||||
|
if (static_cast<unsigned char>(voicePacket.talker) >= Game::MAX_CLIENTS)
|
||||||
|
{
|
||||||
|
Logger::Print(Game::CON_CHANNEL_CLIENT, "Invalid voice packet - talker was {}\n", voicePacket.talker);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CL_IsPlayerMuted_Hk(nullptr, localClientNum, voicePacket.talker))
|
||||||
|
{
|
||||||
|
if ((*Game::cl_voice)->current.enabled)
|
||||||
|
{
|
||||||
|
Game::Voice_IncomingVoiceData(nullptr, voicePacket.talker, reinterpret_cast<unsigned char*>(voicePacket.data), voicePacket.dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::UI_Mute_player(int clientNum, const int localClientNum)
|
||||||
|
{
|
||||||
|
if (Game::cgArray->clientNum != Game::sharedUiInfo->playerClientNums[clientNum])
|
||||||
|
{
|
||||||
|
CL_TogglePlayerMute(localClientNum, Game::sharedUiInfo->playerClientNums[clientNum]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked) void Voice::UI_Mute_Player_Stub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push eax
|
||||||
|
call UI_Mute_player
|
||||||
|
add esp, 8 // Game already pushed localClientNum
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
add esp, 0xC00
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Voice::Voice()
|
||||||
|
{
|
||||||
|
AssertOffset(Game::clientUIActive_t, connectionState, 0x9B8);
|
||||||
|
|
||||||
|
std::memset(voicePackets, 0, sizeof(voicePackets));
|
||||||
|
std::memset(voicePacketCount, 0, sizeof(voicePacketCount));
|
||||||
|
std::memset(s_playerMute, 0, sizeof(s_playerMute));
|
||||||
|
|
||||||
|
// Write voice packets to the server instead of other clients
|
||||||
|
Utils::Hook(0x487935, CL_WriteVoicePacket_Hk, HOOK_CALL).install()->quick();
|
||||||
|
Utils::Hook(0x5AD945, CL_WriteVoicePacket_Hk, HOOK_CALL).install()->quick();
|
||||||
|
Utils::Hook(0x5A9E06, CL_VoicePacket_Hk, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
Utils::Hook(0x4B6250, CL_IsPlayerMuted_Hk, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
Utils::Hook(0x4519F5, SV_SendClientMessages_Stub, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
// Recycle packet handler for 'icanthear'
|
||||||
|
Utils::Hook::Set<const char*>(0x62673F, "v");
|
||||||
|
Utils::Hook(0x626787, SV_VoicePacket, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
Utils::Hook(0x45F041, UI_Mute_Player_Stub, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
Utils::Hook(0x4C6B50, Voice_UnmuteMember_Hk, HOOK_JUMP).install()->quick();
|
||||||
|
Utils::Hook(0x43F460, CL_MutePlayer_Hk, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
sv_voice = Game::Dvar_RegisterBool("sv_voice", false, Game::DVAR_NONE, "Use server side voice communications");
|
||||||
|
}
|
||||||
|
}
|
45
src/Components/Modules/Voice.hpp
Normal file
45
src/Components/Modules/Voice.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Components
|
||||||
|
{
|
||||||
|
class Voice : public Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Voice();
|
||||||
|
|
||||||
|
static bool SV_VoiceEnabled();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr auto MAX_VOICE_PACKET_DATA = 256;
|
||||||
|
static constexpr auto MAX_SERVER_QUEUED_VOICE_PACKETS = 40;
|
||||||
|
|
||||||
|
static Game::VoicePacket_t voicePackets[Game::MAX_CLIENTS][MAX_SERVER_QUEUED_VOICE_PACKETS];
|
||||||
|
static int voicePacketCount[Game::MAX_CLIENTS];
|
||||||
|
|
||||||
|
static bool s_playerMute[Game::MAX_CLIENTS];
|
||||||
|
|
||||||
|
static const Game::dvar_t* sv_voice;
|
||||||
|
|
||||||
|
static void SV_WriteVoiceDataToClient(int clientNum, Game::msg_t* msg);
|
||||||
|
static void SV_SendClientVoiceData(Game::client_t* client);
|
||||||
|
static void SV_SendClientMessages_Stub(Game::client_t* client, Game::msg_t* msg, unsigned char* snapshotMsgBuf);
|
||||||
|
|
||||||
|
static bool OnSameTeam(Game::gentity_s* ent1, Game::gentity_s* ent2);
|
||||||
|
static void SV_QueueVoicePacket(int talkerNum, int clientNum, Game::VoicePacket_t* voicePacket);
|
||||||
|
static void G_BroadcastVoice(Game::gentity_s* talker, Game::VoicePacket_t* voicePacket);
|
||||||
|
static void SV_UserVoice(Game::client_t* cl, Game::msg_t* msg);
|
||||||
|
static void SV_PreGameUserVoice(Game::client_t* cl, Game::msg_t* msg);
|
||||||
|
static void SV_VoicePacket(Game::netadr_t from, Game::msg_t* msg);
|
||||||
|
|
||||||
|
static bool CL_IsPlayerMuted_Hk(Game::SessionData* session, int localClientNum, int muteClientIndex);
|
||||||
|
static void CL_MutePlayer_Hk(Game::SessionData* session, int muteClientIndex);
|
||||||
|
static void Voice_UnmuteMember_Hk(Game::SessionData* session, int clientNum);
|
||||||
|
static void CL_TogglePlayerMute(int localClientNum, int muteClientIndex);
|
||||||
|
|
||||||
|
static void CL_WriteVoicePacket_Hk(int localClientNum);
|
||||||
|
static void CL_VoicePacket_Hk(int localClientNum, Game::msg_t* msg);
|
||||||
|
|
||||||
|
static void UI_Mute_player(int clientNum, int localClientNum);
|
||||||
|
static void UI_Mute_Player_Stub();
|
||||||
|
};
|
||||||
|
}
|
@ -20,8 +20,13 @@ namespace Game
|
|||||||
const dvar_t** sv_mapRotationCurrent = reinterpret_cast<const dvar_t**>(0x2098DF0);
|
const dvar_t** sv_mapRotationCurrent = reinterpret_cast<const dvar_t**>(0x2098DF0);
|
||||||
const dvar_t** sv_maxclients = reinterpret_cast<const dvar_t**>(0x2098D90);
|
const dvar_t** sv_maxclients = reinterpret_cast<const dvar_t**>(0x2098D90);
|
||||||
const dvar_t** sv_cheats = reinterpret_cast<const dvar_t**>(0x2098DE0);
|
const dvar_t** sv_cheats = reinterpret_cast<const dvar_t**>(0x2098DE0);
|
||||||
|
const dvar_t** sv_voiceQuality = reinterpret_cast<const dvar_t**>(0x2098DB0);
|
||||||
|
|
||||||
|
const dvar_t** cl_showSend = reinterpret_cast<const dvar_t**>(0xA1E870);
|
||||||
|
const dvar_t** cl_voice = reinterpret_cast<const dvar_t**>(0xB2BB44);
|
||||||
|
|
||||||
const dvar_t** g_cheats = reinterpret_cast<const dvar_t**>(0x1A45D54);
|
const dvar_t** g_cheats = reinterpret_cast<const dvar_t**>(0x1A45D54);
|
||||||
|
const dvar_t** g_deadChat = reinterpret_cast<const dvar_t**>(0x19BD5DC);
|
||||||
|
|
||||||
const dvar_t** version = reinterpret_cast<const dvar_t**>(0x1AD7930);
|
const dvar_t** version = reinterpret_cast<const dvar_t**>(0x1AD7930);
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,13 @@ namespace Game
|
|||||||
extern const dvar_t** sv_mapRotationCurrent;
|
extern const dvar_t** sv_mapRotationCurrent;
|
||||||
extern const dvar_t** sv_maxclients;
|
extern const dvar_t** sv_maxclients;
|
||||||
extern const dvar_t** sv_cheats;
|
extern const dvar_t** sv_cheats;
|
||||||
|
extern const dvar_t** sv_voiceQuality;
|
||||||
|
|
||||||
|
extern const dvar_t** cl_showSend;
|
||||||
|
extern const dvar_t** cl_voice;
|
||||||
|
|
||||||
extern const dvar_t** g_cheats;
|
extern const dvar_t** g_cheats;
|
||||||
|
extern const dvar_t** g_deadChat;
|
||||||
|
|
||||||
extern const dvar_t** version;
|
extern const dvar_t** version;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,7 @@ namespace Game
|
|||||||
CL_ConsoleFixPosition_t CL_ConsoleFixPosition = CL_ConsoleFixPosition_t(0x44A430);
|
CL_ConsoleFixPosition_t CL_ConsoleFixPosition = CL_ConsoleFixPosition_t(0x44A430);
|
||||||
CL_GetLocalClientActiveCount_t CL_GetLocalClientActiveCount = CL_GetLocalClientActiveCount_t(0x5BAD90);
|
CL_GetLocalClientActiveCount_t CL_GetLocalClientActiveCount = CL_GetLocalClientActiveCount_t(0x5BAD90);
|
||||||
CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum = CL_ControllerIndexFromClientNum_t(0x449E30);
|
CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum = CL_ControllerIndexFromClientNum_t(0x449E30);
|
||||||
|
CL_MouseEvent_t CL_MouseEvent = CL_MouseEvent_t(0x4D7C50);
|
||||||
|
|
||||||
Cmd_AddCommand_t Cmd_AddCommand = Cmd_AddCommand_t(0x470090);
|
Cmd_AddCommand_t Cmd_AddCommand = Cmd_AddCommand_t(0x470090);
|
||||||
Cmd_AddServerCommand_t Cmd_AddServerCommand = Cmd_AddServerCommand_t(0x4DCE00);
|
Cmd_AddServerCommand_t Cmd_AddServerCommand = Cmd_AddServerCommand_t(0x4DCE00);
|
||||||
@ -254,6 +255,7 @@ namespace Game
|
|||||||
NET_StringToAdr_t NET_StringToAdr = NET_StringToAdr_t(0x409010);
|
NET_StringToAdr_t NET_StringToAdr = NET_StringToAdr_t(0x409010);
|
||||||
NET_OutOfBandPrint_t NET_OutOfBandPrint = NET_OutOfBandPrint_t(0x4AEF00);
|
NET_OutOfBandPrint_t NET_OutOfBandPrint = NET_OutOfBandPrint_t(0x4AEF00);
|
||||||
NET_OutOfBandData_t NET_OutOfBandData = NET_OutOfBandData_t(0x49C7E0);
|
NET_OutOfBandData_t NET_OutOfBandData = NET_OutOfBandData_t(0x49C7E0);
|
||||||
|
NET_OutOfBandVoiceData_t NET_OutOfBandVoiceData = NET_OutOfBandVoiceData_t(0x4FCC90);
|
||||||
|
|
||||||
Live_MPAcceptInvite_t Live_MPAcceptInvite = Live_MPAcceptInvite_t(0x420A6D);
|
Live_MPAcceptInvite_t Live_MPAcceptInvite = Live_MPAcceptInvite_t(0x420A6D);
|
||||||
Live_GetMapIndex_t Live_GetMapIndex = Live_GetMapIndex_t(0x4F6440);
|
Live_GetMapIndex_t Live_GetMapIndex = Live_GetMapIndex_t(0x4F6440);
|
||||||
@ -273,6 +275,7 @@ namespace Game
|
|||||||
PartyHost_CountMembers_t PartyHost_CountMembers = PartyHost_CountMembers_t(0x497330);
|
PartyHost_CountMembers_t PartyHost_CountMembers = PartyHost_CountMembers_t(0x497330);
|
||||||
PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot = PartyHost_GetMemberAddressBySlot_t(0x44E100);
|
PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot = PartyHost_GetMemberAddressBySlot_t(0x44E100);
|
||||||
PartyHost_GetMemberName_t PartyHost_GetMemberName = PartyHost_GetMemberName_t(0x44BE90);
|
PartyHost_GetMemberName_t PartyHost_GetMemberName = PartyHost_GetMemberName_t(0x44BE90);
|
||||||
|
Party_InParty_t Party_InParty = Party_InParty_t(0x4F10C0);
|
||||||
|
|
||||||
Playlist_ParsePlaylists_t Playlist_ParsePlaylists = Playlist_ParsePlaylists_t(0x4295A0);
|
Playlist_ParsePlaylists_t Playlist_ParsePlaylists = Playlist_ParsePlaylists_t(0x4295A0);
|
||||||
|
|
||||||
@ -388,6 +391,7 @@ namespace Game
|
|||||||
SV_DropClient_t SV_DropClient = SV_DropClient_t(0x4D1600);
|
SV_DropClient_t SV_DropClient = SV_DropClient_t(0x4D1600);
|
||||||
SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0);
|
SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0);
|
||||||
SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390);
|
SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390);
|
||||||
|
SV_FindClientByAddress_t SV_FindClientByAddress = SV_FindClientByAddress_t(0x44F450);
|
||||||
|
|
||||||
Sys_FreeFileList_t Sys_FreeFileList = Sys_FreeFileList_t(0x4D8580);
|
Sys_FreeFileList_t Sys_FreeFileList = Sys_FreeFileList_t(0x4D8580);
|
||||||
Sys_IsDatabaseReady_t Sys_IsDatabaseReady = Sys_IsDatabaseReady_t(0x4CA4A0);
|
Sys_IsDatabaseReady_t Sys_IsDatabaseReady = Sys_IsDatabaseReady_t(0x4CA4A0);
|
||||||
@ -458,7 +462,6 @@ namespace Game
|
|||||||
PM_GetEffectiveStance_t PM_GetEffectiveStance = PM_GetEffectiveStance_t(0x412540);
|
PM_GetEffectiveStance_t PM_GetEffectiveStance = PM_GetEffectiveStance_t(0x412540);
|
||||||
PM_UpdateLean_t PM_UpdateLean = PM_UpdateLean_t(0x43DED0);
|
PM_UpdateLean_t PM_UpdateLean = PM_UpdateLean_t(0x43DED0);
|
||||||
|
|
||||||
CL_MouseEvent_t CL_MouseEvent = CL_MouseEvent_t(0x4D7C50);
|
|
||||||
IN_RecenterMouse_t IN_RecenterMouse = IN_RecenterMouse_t(0x463D80);
|
IN_RecenterMouse_t IN_RecenterMouse = IN_RecenterMouse_t(0x463D80);
|
||||||
|
|
||||||
IN_MouseMove_t IN_MouseMove = IN_MouseMove_t(0x64C490);
|
IN_MouseMove_t IN_MouseMove = IN_MouseMove_t(0x64C490);
|
||||||
@ -483,6 +486,7 @@ namespace Game
|
|||||||
I_strncpyz_t I_strncpyz = I_strncpyz_t(0x4D6F80);
|
I_strncpyz_t I_strncpyz = I_strncpyz_t(0x4D6F80);
|
||||||
|
|
||||||
XNAddrToString_t XNAddrToString = XNAddrToString_t(0x452690);
|
XNAddrToString_t XNAddrToString = XNAddrToString_t(0x452690);
|
||||||
|
Voice_IncomingVoiceData_t Voice_IncomingVoiceData = Voice_IncomingVoiceData_t(0x5001A0);
|
||||||
|
|
||||||
XAssetHeader* DB_XAssetPool = reinterpret_cast<XAssetHeader*>(0x7998A8);
|
XAssetHeader* DB_XAssetPool = reinterpret_cast<XAssetHeader*>(0x7998A8);
|
||||||
unsigned int* g_poolSize = reinterpret_cast<unsigned int*>(0x7995E8);
|
unsigned int* g_poolSize = reinterpret_cast<unsigned int*>(0x7995E8);
|
||||||
@ -520,6 +524,8 @@ namespace Game
|
|||||||
PartyData* g_lobbyData = reinterpret_cast<PartyData*>(0x1081C00);
|
PartyData* g_lobbyData = reinterpret_cast<PartyData*>(0x1081C00);
|
||||||
PartyData* g_partyData = reinterpret_cast<PartyData*>(0x107E500);
|
PartyData* g_partyData = reinterpret_cast<PartyData*>(0x107E500);
|
||||||
|
|
||||||
|
SessionData* g_serverSession = reinterpret_cast<SessionData*>(0x66B7008);
|
||||||
|
|
||||||
int* numIP = reinterpret_cast<int*>(0x64A1E68);
|
int* numIP = reinterpret_cast<int*>(0x64A1E68);
|
||||||
netIP_t* localIP = reinterpret_cast<netIP_t*>(0x64A1E28);
|
netIP_t* localIP = reinterpret_cast<netIP_t*>(0x64A1E28);
|
||||||
|
|
||||||
@ -583,7 +589,7 @@ namespace Game
|
|||||||
field_t* g_consoleField = reinterpret_cast<field_t*>(0xA1B6B0);
|
field_t* g_consoleField = reinterpret_cast<field_t*>(0xA1B6B0);
|
||||||
|
|
||||||
clientStatic_t* cls = reinterpret_cast<clientStatic_t*>(0xA7FE90);
|
clientStatic_t* cls = reinterpret_cast<clientStatic_t*>(0xA7FE90);
|
||||||
clientUIActive_t* clientUIActives = reinterpret_cast<clientUIActive_t*>(0xB2BB8A);
|
clientUIActive_t* clientUIActives = reinterpret_cast<clientUIActive_t*>(0xB2BB88);
|
||||||
|
|
||||||
sharedUiInfo_t* sharedUiInfo = reinterpret_cast<sharedUiInfo_t*>(0x62E4B78);
|
sharedUiInfo_t* sharedUiInfo = reinterpret_cast<sharedUiInfo_t*>(0x62E4B78);
|
||||||
ScreenPlacement* scrPlaceFull = reinterpret_cast<ScreenPlacement*>(0x10843F0);
|
ScreenPlacement* scrPlaceFull = reinterpret_cast<ScreenPlacement*>(0x10843F0);
|
||||||
@ -648,6 +654,10 @@ namespace Game
|
|||||||
|
|
||||||
GamerSettingState* gamerSettings = reinterpret_cast<GamerSettingState*>(0x107D3E8);
|
GamerSettingState* gamerSettings = reinterpret_cast<GamerSettingState*>(0x107D3E8);
|
||||||
|
|
||||||
|
voiceCommunication_t* cl_voiceCommunication = reinterpret_cast<voiceCommunication_t*>(0x1079DA0);
|
||||||
|
|
||||||
|
volatile long* sv_thread_owns_game = reinterpret_cast<volatile long*>(0x2089DB8);
|
||||||
|
|
||||||
void Sys_LockRead(FastCriticalSection* critSect)
|
void Sys_LockRead(FastCriticalSection* critSect)
|
||||||
{
|
{
|
||||||
InterlockedIncrement(&critSect->readCount);
|
InterlockedIncrement(&critSect->readCount);
|
||||||
@ -853,6 +863,11 @@ namespace Game
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SV_GetServerThreadOwnsGame()
|
||||||
|
{
|
||||||
|
return *sv_thread_owns_game;
|
||||||
|
}
|
||||||
|
|
||||||
void SV_GameDropClient(int clientNum, const char* reason)
|
void SV_GameDropClient(int clientNum, const char* reason)
|
||||||
{
|
{
|
||||||
assert((*sv_maxclients)->current.integer >= 1 && (*sv_maxclients)->current.integer <= 18);
|
assert((*sv_maxclients)->current.integer >= 1 && (*sv_maxclients)->current.integer <= 18);
|
||||||
@ -967,6 +982,28 @@ namespace Game
|
|||||||
return atoi(StringTable_Lookup(rankTable, 0, maxrank, 7));
|
return atoi(StringTable_Lookup(rankTable, 0, maxrank, 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientConnection_t* CL_GetLocalClientConnection(const int localClientNum)
|
||||||
|
{
|
||||||
|
assert(clientConnections);
|
||||||
|
AssertIn(localClientNum, MAX_LOCAL_CLIENTS);
|
||||||
|
|
||||||
|
return &clientConnections[localClientNum];
|
||||||
|
}
|
||||||
|
|
||||||
|
connstate_t CL_GetLocalClientConnectionState(const int localClientNum)
|
||||||
|
{
|
||||||
|
AssertIn(localClientNum, STATIC_MAX_LOCAL_CLIENTS);
|
||||||
|
|
||||||
|
return clientUIActives[localClientNum].connectionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
voiceCommunication_t* CL_GetLocalClientVoiceCommunication([[maybe_unused]] const int localClientNum)
|
||||||
|
{
|
||||||
|
AssertIn(localClientNum, STATIC_MAX_LOCAL_CLIENTS);
|
||||||
|
|
||||||
|
return cl_voiceCommunication;
|
||||||
|
}
|
||||||
|
|
||||||
void Vec2UnpackTexCoords(const PackedTexCoords in, vec2_t* out)
|
void Vec2UnpackTexCoords(const PackedTexCoords in, vec2_t* out)
|
||||||
{
|
{
|
||||||
unsigned int v3; // xmm1_4
|
unsigned int v3; // xmm1_4
|
||||||
|
@ -145,6 +145,9 @@ namespace Game
|
|||||||
typedef int(__cdecl * CL_ControllerIndexFromClientNum_t)(int localActiveClientNum);
|
typedef int(__cdecl * CL_ControllerIndexFromClientNum_t)(int localActiveClientNum);
|
||||||
extern CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum;
|
extern CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum;
|
||||||
|
|
||||||
|
typedef int(__cdecl * CL_MouseEvent_t)(int x, int y, int dx, int dy);
|
||||||
|
extern CL_MouseEvent_t CL_MouseEvent;
|
||||||
|
|
||||||
typedef void(__cdecl * Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_t* allocedCmd, bool isKey);
|
typedef void(__cdecl * Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_t* allocedCmd, bool isKey);
|
||||||
extern Cmd_AddCommand_t Cmd_AddCommand;
|
extern Cmd_AddCommand_t Cmd_AddCommand;
|
||||||
|
|
||||||
@ -576,7 +579,7 @@ namespace Game
|
|||||||
typedef void(__cdecl * UI_ReplaceConversions_t)(const char* sourceString, ConversionArguments* arguments, char* outputString, size_t outputStringSize);
|
typedef void(__cdecl * UI_ReplaceConversions_t)(const char* sourceString, ConversionArguments* arguments, char* outputString, size_t outputStringSize);
|
||||||
extern UI_ReplaceConversions_t UI_ReplaceConversions;
|
extern UI_ReplaceConversions_t UI_ReplaceConversions;
|
||||||
|
|
||||||
typedef void(__cdecl * MSG_Init_t)(msg_t* buf, char* data, int length);
|
typedef void(__cdecl * MSG_Init_t)(msg_t* buf, unsigned char* data, int length);
|
||||||
extern MSG_Init_t MSG_Init;
|
extern MSG_Init_t MSG_Init;
|
||||||
|
|
||||||
typedef void(__cdecl * MSG_ReadData_t)(msg_t* msg, void* data, int len);
|
typedef void(__cdecl * MSG_ReadData_t)(msg_t* msg, void* data, int len);
|
||||||
@ -591,7 +594,7 @@ namespace Game
|
|||||||
typedef int(__cdecl * MSG_ReadBits_t)(msg_t* msg, int bits);
|
typedef int(__cdecl * MSG_ReadBits_t)(msg_t* msg, int bits);
|
||||||
extern MSG_ReadBits_t MSG_ReadBits;
|
extern MSG_ReadBits_t MSG_ReadBits;
|
||||||
|
|
||||||
typedef short(__cdecl * MSG_ReadShort_t)(msg_t* msg);
|
typedef int(__cdecl * MSG_ReadShort_t)(msg_t* msg);
|
||||||
extern MSG_ReadShort_t MSG_ReadShort;
|
extern MSG_ReadShort_t MSG_ReadShort;
|
||||||
|
|
||||||
typedef __int64(__cdecl * MSG_ReadInt64_t)(msg_t* msg);
|
typedef __int64(__cdecl * MSG_ReadInt64_t)(msg_t* msg);
|
||||||
@ -609,7 +612,7 @@ namespace Game
|
|||||||
typedef int(__cdecl * MSG_ReadBitsCompress_t)(const char *from, char *to, int size);
|
typedef int(__cdecl * MSG_ReadBitsCompress_t)(const char *from, char *to, int size);
|
||||||
extern MSG_ReadBitsCompress_t MSG_ReadBitsCompress;
|
extern MSG_ReadBitsCompress_t MSG_ReadBitsCompress;
|
||||||
|
|
||||||
typedef void(__cdecl * MSG_WriteByte_t)(msg_t* msg, unsigned char c);
|
typedef void(__cdecl * MSG_WriteByte_t)(msg_t* msg, int c);
|
||||||
extern MSG_WriteByte_t MSG_WriteByte;
|
extern MSG_WriteByte_t MSG_WriteByte;
|
||||||
|
|
||||||
typedef void(__cdecl * MSG_WriteData_t)(msg_t *buf, const void *data, int length);
|
typedef void(__cdecl * MSG_WriteData_t)(msg_t *buf, const void *data, int length);
|
||||||
@ -618,7 +621,7 @@ namespace Game
|
|||||||
typedef void(__cdecl * MSG_WriteLong_t)(msg_t *msg, int c);
|
typedef void(__cdecl * MSG_WriteLong_t)(msg_t *msg, int c);
|
||||||
extern MSG_WriteLong_t MSG_WriteLong;
|
extern MSG_WriteLong_t MSG_WriteLong;
|
||||||
|
|
||||||
typedef void(__cdecl * MSG_WriteShort_t)(msg_t* msg, short s);
|
typedef void(__cdecl * MSG_WriteShort_t)(msg_t* msg, int s);
|
||||||
extern MSG_WriteShort_t MSG_WriteShort;
|
extern MSG_WriteShort_t MSG_WriteShort;
|
||||||
|
|
||||||
typedef void(__cdecl * MSG_WriteString_t)(msg_t* msg, const char *str);
|
typedef void(__cdecl * MSG_WriteString_t)(msg_t* msg, const char *str);
|
||||||
@ -660,6 +663,9 @@ namespace Game
|
|||||||
typedef void(__cdecl * NET_OutOfBandData_t)(netsrc_t sock, netadr_t adr, const char *format, int len);
|
typedef void(__cdecl * NET_OutOfBandData_t)(netsrc_t sock, netadr_t adr, const char *format, int len);
|
||||||
extern NET_OutOfBandData_t NET_OutOfBandData;
|
extern NET_OutOfBandData_t NET_OutOfBandData;
|
||||||
|
|
||||||
|
typedef int(__cdecl * NET_OutOfBandVoiceData_t)(netsrc_t sock, netadr_t adr, unsigned char* format, int len, bool voiceData);
|
||||||
|
extern NET_OutOfBandVoiceData_t NET_OutOfBandVoiceData;
|
||||||
|
|
||||||
typedef void(__cdecl * Live_MPAcceptInvite_t)(_XSESSION_INFO *hostInfo, const int controllerIndex, bool fromGameInvite);
|
typedef void(__cdecl * Live_MPAcceptInvite_t)(_XSESSION_INFO *hostInfo, const int controllerIndex, bool fromGameInvite);
|
||||||
extern Live_MPAcceptInvite_t Live_MPAcceptInvite;
|
extern Live_MPAcceptInvite_t Live_MPAcceptInvite;
|
||||||
|
|
||||||
@ -702,6 +708,9 @@ namespace Game
|
|||||||
typedef const char *(__cdecl * PartyHost_GetMemberName_t)(PartyData* party, const int clientNum);
|
typedef const char *(__cdecl * PartyHost_GetMemberName_t)(PartyData* party, const int clientNum);
|
||||||
extern PartyHost_GetMemberName_t PartyHost_GetMemberName;
|
extern PartyHost_GetMemberName_t PartyHost_GetMemberName;
|
||||||
|
|
||||||
|
typedef int(__cdecl * Party_InParty_t)(PartyData* party);
|
||||||
|
extern Party_InParty_t Party_InParty;
|
||||||
|
|
||||||
typedef void(__cdecl * Playlist_ParsePlaylists_t)(const char* data);
|
typedef void(__cdecl * Playlist_ParsePlaylists_t)(const char* data);
|
||||||
extern Playlist_ParsePlaylists_t Playlist_ParsePlaylists;
|
extern Playlist_ParsePlaylists_t Playlist_ParsePlaylists;
|
||||||
|
|
||||||
@ -957,6 +966,9 @@ namespace Game
|
|||||||
typedef client_t*(__cdecl * SV_GetPlayerByNum_t)();
|
typedef client_t*(__cdecl * SV_GetPlayerByNum_t)();
|
||||||
extern SV_GetPlayerByNum_t SV_GetPlayerByNum;
|
extern SV_GetPlayerByNum_t SV_GetPlayerByNum;
|
||||||
|
|
||||||
|
typedef client_t*(__cdecl * SV_FindClientByAddress_t)(netadr_t from, int qport, int remoteClientIndex);
|
||||||
|
extern SV_FindClientByAddress_t SV_FindClientByAddress;
|
||||||
|
|
||||||
typedef void(__cdecl * Sys_Error_t)(const char* error, ...);
|
typedef void(__cdecl * Sys_Error_t)(const char* error, ...);
|
||||||
extern Sys_Error_t Sys_Error;
|
extern Sys_Error_t Sys_Error;
|
||||||
|
|
||||||
@ -1116,9 +1128,6 @@ namespace Game
|
|||||||
typedef void(__cdecl * PM_UpdateLean_t)(playerState_s* ps, float msec, usercmd_s* cmd, void(*capsuleTrace)(trace_t*, const float*, const float*, const Bounds*, int, int));
|
typedef void(__cdecl * PM_UpdateLean_t)(playerState_s* ps, float msec, usercmd_s* cmd, void(*capsuleTrace)(trace_t*, const float*, const float*, const Bounds*, int, int));
|
||||||
extern PM_UpdateLean_t PM_UpdateLean;
|
extern PM_UpdateLean_t PM_UpdateLean;
|
||||||
|
|
||||||
typedef int(__cdecl * CL_MouseEvent_t)(int x, int y, int dx, int dy);
|
|
||||||
extern CL_MouseEvent_t CL_MouseEvent;
|
|
||||||
|
|
||||||
typedef void(__cdecl * IN_RecenterMouse_t)();
|
typedef void(__cdecl * IN_RecenterMouse_t)();
|
||||||
extern IN_RecenterMouse_t IN_RecenterMouse;
|
extern IN_RecenterMouse_t IN_RecenterMouse;
|
||||||
|
|
||||||
@ -1164,6 +1173,9 @@ namespace Game
|
|||||||
typedef void(__cdecl * XNAddrToString_t)(const XNADDR* xnaddr, char* str);
|
typedef void(__cdecl * XNAddrToString_t)(const XNADDR* xnaddr, char* str);
|
||||||
extern XNAddrToString_t XNAddrToString;
|
extern XNAddrToString_t XNAddrToString;
|
||||||
|
|
||||||
|
typedef int(__cdecl * Voice_IncomingVoiceData_t)(const SessionData* session, int clientNum, unsigned char* data, int size);
|
||||||
|
extern Voice_IncomingVoiceData_t Voice_IncomingVoiceData;
|
||||||
|
|
||||||
constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1;
|
constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1;
|
||||||
constexpr std::size_t MAX_LOCAL_CLIENTS = 1;
|
constexpr std::size_t MAX_LOCAL_CLIENTS = 1;
|
||||||
constexpr std::size_t MAX_CLIENTS = 18;
|
constexpr std::size_t MAX_CLIENTS = 18;
|
||||||
@ -1205,6 +1217,8 @@ namespace Game
|
|||||||
extern PartyData* g_lobbyData;
|
extern PartyData* g_lobbyData;
|
||||||
extern PartyData* g_partyData;
|
extern PartyData* g_partyData;
|
||||||
|
|
||||||
|
extern SessionData* g_serverSession;
|
||||||
|
|
||||||
extern int* numIP;
|
extern int* numIP;
|
||||||
extern netIP_t* localIP;
|
extern netIP_t* localIP;
|
||||||
|
|
||||||
@ -1339,6 +1353,10 @@ namespace Game
|
|||||||
|
|
||||||
extern GamerSettingState* gamerSettings;
|
extern GamerSettingState* gamerSettings;
|
||||||
|
|
||||||
|
extern voiceCommunication_t* cl_voiceCommunication;
|
||||||
|
|
||||||
|
extern volatile long* sv_thread_owns_game;
|
||||||
|
|
||||||
void Sys_LockRead(FastCriticalSection* critSect);
|
void Sys_LockRead(FastCriticalSection* critSect);
|
||||||
void Sys_UnlockRead(FastCriticalSection* critSect);
|
void Sys_UnlockRead(FastCriticalSection* critSect);
|
||||||
|
|
||||||
@ -1377,6 +1395,7 @@ namespace Game
|
|||||||
void R_LoadSunThroughDvars(const char* mapname, sunflare_t* sun);
|
void R_LoadSunThroughDvars(const char* mapname, sunflare_t* sun);
|
||||||
void R_SetSunFromDvars(sunflare_t* sun);
|
void R_SetSunFromDvars(sunflare_t* sun);
|
||||||
|
|
||||||
|
int SV_GetServerThreadOwnsGame();
|
||||||
void SV_GameDropClient(int clientNum, const char* reason);
|
void SV_GameDropClient(int clientNum, const char* reason);
|
||||||
void SV_DropAllBots();
|
void SV_DropAllBots();
|
||||||
void SV_BotUserMove(client_t* client);
|
void SV_BotUserMove(client_t* client);
|
||||||
@ -1399,6 +1418,9 @@ namespace Game
|
|||||||
void Com_SetParseNegativeNumbers(int parse);
|
void Com_SetParseNegativeNumbers(int parse);
|
||||||
|
|
||||||
int CL_GetMaxXP();
|
int CL_GetMaxXP();
|
||||||
|
clientConnection_t* CL_GetLocalClientConnection(int localClientNum);
|
||||||
|
connstate_t CL_GetLocalClientConnectionState(int localClientNum);
|
||||||
|
voiceCommunication_t* CL_GetLocalClientVoiceCommunication(int localClientNum);
|
||||||
|
|
||||||
void Image_Setup(GfxImage* image, unsigned int width, unsigned int height, unsigned int depth, unsigned int flags, _D3DFORMAT format);
|
void Image_Setup(GfxImage* image, unsigned int width, unsigned int height, unsigned int depth, unsigned int flags, _D3DFORMAT format);
|
||||||
|
|
||||||
|
@ -5234,7 +5234,7 @@ namespace Game
|
|||||||
int stringOffsets[4139];
|
int stringOffsets[4139];
|
||||||
char stringData[131072];
|
char stringData[131072];
|
||||||
int dataCount;
|
int dataCount;
|
||||||
} gameState;
|
};
|
||||||
|
|
||||||
struct HunkUser
|
struct HunkUser
|
||||||
{
|
{
|
||||||
@ -5708,8 +5708,8 @@ namespace Game
|
|||||||
{
|
{
|
||||||
int overflowed;
|
int overflowed;
|
||||||
int readOnly;
|
int readOnly;
|
||||||
char *data;
|
unsigned char *data;
|
||||||
char *splitData;
|
unsigned char *splitData;
|
||||||
int maxsize;
|
int maxsize;
|
||||||
int cursize;
|
int cursize;
|
||||||
int splitSize;
|
int splitSize;
|
||||||
@ -8761,26 +8761,15 @@ namespace Game
|
|||||||
bool isRunning;
|
bool isRunning;
|
||||||
bool cgameInitialized;
|
bool cgameInitialized;
|
||||||
bool cgameInitCalled;
|
bool cgameInitCalled;
|
||||||
bool mapPreloaded;
|
unsigned char __pad0[0x9AC];
|
||||||
clientMigState_t migrationState;
|
|
||||||
MigrationPers migrationPers;
|
|
||||||
MigrationVerboseState verboseMigrationState;
|
|
||||||
int verboseMigrationData;
|
|
||||||
int keyCatchers;
|
int keyCatchers;
|
||||||
bool displayHUDWithKeycatchUI;
|
bool displayHUDWithKeycatchUI;
|
||||||
connstate_t connectionState;
|
connstate_t connectionState;
|
||||||
bool invited;
|
unsigned char __pad1[0x138];
|
||||||
char itemsUnlocked[256];
|
|
||||||
bool itemsUnlockedInited;
|
|
||||||
bool itemsUnlockedLastGameDirty;
|
|
||||||
unsigned __int16 itemsUnlockedLastGame[16];
|
|
||||||
int itemsUnlockedLastGameCount;
|
|
||||||
char* itemsUnlockedBuffer;
|
|
||||||
int itemsUnlockedLocalClientNum;
|
|
||||||
int itemsUnlockedControllerIndex;
|
|
||||||
int itemsUnlockedStatsSource;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(clientUIActive_t) == 0xAF4);
|
||||||
|
|
||||||
enum msgLocErrType_t
|
enum msgLocErrType_t
|
||||||
{
|
{
|
||||||
LOCMSG_SAFE = 0x0,
|
LOCMSG_SAFE = 0x0,
|
||||||
@ -8839,6 +8828,28 @@ namespace Game
|
|||||||
CRITSECT_COUNT,
|
CRITSECT_COUNT,
|
||||||
}; // May be incorrect
|
}; // May be incorrect
|
||||||
|
|
||||||
|
struct ClientVoicePacket_t
|
||||||
|
{
|
||||||
|
char data[256];
|
||||||
|
int dataSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct voiceCommunication_t
|
||||||
|
{
|
||||||
|
ClientVoicePacket_t voicePackets[10];
|
||||||
|
int voicePacketCount;
|
||||||
|
int voicePacketLastTransmit;
|
||||||
|
int packetsPerSec;
|
||||||
|
int packetsPerSecStart;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoicePacket_t
|
||||||
|
{
|
||||||
|
char talker;
|
||||||
|
char data[256];
|
||||||
|
int dataSize;
|
||||||
|
};
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#ifndef IDA
|
#ifndef IDA
|
||||||
|
Loading…
Reference in New Issue
Block a user