iw4x-client/src/Components/Modules/Playlist.cpp

192 lines
5.4 KiB
C++
Raw Normal View History

2022-02-27 07:53:44 -05:00
#include <STDInclude.hpp>
2017-01-19 16:23:59 -05:00
namespace Components
{
std::string Playlist::CurrentPlaylistBuffer;
std::string Playlist::ReceivedPlaylistBuffer;
std::unordered_map<const void*, std::string> Playlist::MapRelocation;
void Playlist::LoadPlaylist()
{
// Check if playlist already loaded
2022-12-25 12:23:53 -05:00
if (*Game::s_havePlaylists) return;
2017-01-19 16:23:59 -05:00
// Don't load playlists when dedi and no party
if (Dedicated::IsEnabled() && !Dvar::Var("party_enable").get<bool>())
{
2022-12-25 12:23:53 -05:00
*Game::s_havePlaylists = true;
2017-01-19 16:23:59 -05:00
Dvar::Var("xblive_privateserver").set(true);
return;
}
Dvar::Var("xblive_privateserver").set(false);
2022-12-25 12:23:53 -05:00
const auto playlistFilename = Dvar::Var("playlistFilename").get<std::string>();
2017-01-19 16:23:59 -05:00
FileSystem::File playlist(playlistFilename);
if (playlist.exists())
{
2022-06-12 17:07:53 -04:00
Logger::Print("Parsing playlist '{}'...\n", playlist.getName());
2017-01-19 16:23:59 -05:00
Game::Playlist_ParsePlaylists(playlist.getBuffer().data());
2022-12-25 12:23:53 -05:00
*Game::s_havePlaylists = true;
2017-01-19 16:23:59 -05:00
}
else
{
2022-06-12 17:07:53 -04:00
Logger::Print("Unable to load playlist '{}'!\n", playlist.getName());
2017-01-19 16:23:59 -05:00
}
}
2022-12-25 12:23:53 -05:00
char* Playlist::Com_ParseOnLine_Hk(const char** data_p)
2017-01-19 16:23:59 -05:00
{
2022-12-25 12:23:53 -05:00
MapRelocation.clear();
CurrentPlaylistBuffer = Utils::Compression::ZLib::Compress(*data_p);
return Game::Com_ParseOnLine(data_p);
2017-01-19 16:23:59 -05:00
}
2022-05-20 18:12:46 -04:00
void Playlist::PlaylistRequest(const Network::Address& address, [[maybe_unused]] const std::string& data)
2017-01-19 16:23:59 -05:00
{
2022-12-25 12:23:53 -05:00
const auto* password = (*Game::g_password)->current.string;
2022-05-20 18:12:46 -04:00
2022-12-25 12:23:53 -05:00
if (*password)
{
if (password != data)
{
Network::SendCommand(address, "playlistInvalidPassword");
return;
}
}
2017-01-19 16:23:59 -05:00
Logger::Print("Received playlist request, sending currently stored buffer.\n");
2022-12-25 12:23:53 -05:00
std::string compressedList = CurrentPlaylistBuffer;
2017-01-19 16:23:59 -05:00
Proto::Party::Playlist list;
list.set_hash(Utils::Cryptography::JenkinsOneAtATime::Compute(compressedList));
list.set_buffer(compressedList);
Network::SendCommand(address, "playlistResponse", list.SerializeAsString());
}
2022-12-25 12:23:53 -05:00
void Playlist::PlaylistResponse(const Network::Address& address, [[maybe_unused]] const std::string& data)
2017-01-19 16:23:59 -05:00
{
2022-12-25 12:23:53 -05:00
if (!Party::PlaylistAwaiting())
2017-01-19 16:23:59 -05:00
{
2022-12-25 12:23:53 -05:00
Logger::Print("Received stray playlist response, ignoring it.\n");
return;
}
if (address != Party::Target())
{
Logger::Print("Received playlist from someone else than our target host, ignoring it.\n");
return;
}
Proto::Party::Playlist list;
if (!list.ParseFromString(data))
{
Party::PlaylistError(std::format("Received playlist response from {}, but it is invalid.", address.getString()));
ReceivedPlaylistBuffer.clear();
2017-01-19 16:23:59 -05:00
}
else
{
2022-12-25 12:23:53 -05:00
// Generate buffer and hash
const auto& compressedData = list.buffer();
const auto hash = Utils::Cryptography::JenkinsOneAtATime::Compute(compressedData);
// Validate hashes
if (hash != list.hash())
{
Party::PlaylistError(std::format("Received playlist response from {}, but the checksum did not match ({} != {}).", address.getString(), list.hash(), hash));
ReceivedPlaylistBuffer.clear();
return;
}
// Decompress buffer
ReceivedPlaylistBuffer = Utils::Compression::ZLib::Decompress(compressedData);
// Load and continue connection
Logger::Print("Received playlist, loading and continuing connection...\n");
Game::Playlist_ParsePlaylists(ReceivedPlaylistBuffer.data());
Party::PlaylistContinue();
2017-01-19 16:23:59 -05:00
}
}
2022-05-20 18:12:46 -04:00
void Playlist::PlaylistInvalidPassword([[maybe_unused]] const Network::Address& address, [[maybe_unused]] const std::string& data)
{
Party::PlaylistError("Error: Invalid Password for Party.");
}
2022-12-25 12:23:53 -05:00
void Playlist::MapNameCopy(char* dest, const char* src, int destsize)
2017-01-19 16:23:59 -05:00
{
Utils::Hook::Call<void(char*, const char*, int)>(0x4D6F80)(dest, src, destsize);
2022-12-25 12:23:53 -05:00
MapRelocation[dest] = src;
2017-01-19 16:23:59 -05:00
}
2022-12-25 12:23:53 -05:00
void Playlist::SetMapName(const char* dvarName, const char* value)
2017-01-19 16:23:59 -05:00
{
2022-12-25 12:23:53 -05:00
auto i = MapRelocation.find(value);
if (i != MapRelocation.end())
2017-01-19 16:23:59 -05:00
{
value = i->second.data();
}
2022-12-25 12:23:53 -05:00
Game::Dvar_SetStringByName(dvarName, value);
2017-01-19 16:23:59 -05:00
}
int Playlist::GetMapIndex(const char* mapname)
{
2022-12-25 12:23:53 -05:00
auto i = MapRelocation.find(mapname);
if (i != MapRelocation.end())
2017-01-19 16:23:59 -05:00
{
mapname = i->second.data();
}
return Game::Live_GetMapIndex(mapname);
}
Playlist::Playlist()
{
// Default playlists
2020-12-09 14:13:34 -05:00
Utils::Hook::Set<const char*>(0x60B06E, "playlists_default.info");
2017-01-19 16:23:59 -05:00
2022-12-25 12:23:53 -05:00
// Disable playlist download function
2017-01-19 16:23:59 -05:00
Utils::Hook::Set<BYTE>(0x4D4790, 0xC3);
// Load playlist, but don't delete it
Utils::Hook::Nop(0x4D6EBB, 5);
Utils::Hook::Nop(0x4D6E67, 5);
Utils::Hook::Nop(0x4D6E71, 2);
2022-12-25 12:23:53 -05:00
// Disable Playlist_ValidatePlaylistNum
2017-01-19 16:23:59 -05:00
Utils::Hook::Set<BYTE>(0x4B1170, 0xC3);
2022-12-25 12:23:53 -05:00
// Disable playlist checking
Utils::Hook::Set<BYTE>(0x5B69E9, 0xEB); // Too new
Utils::Hook::Set<BYTE>(0x5B696E, 0xEB); // Too old
2017-01-19 16:23:59 -05:00
2022-12-25 12:23:53 -05:00
// Got playlists is true
2017-01-19 16:23:59 -05:00
//Utils::Hook::Set<bool>(0x1AD3680, true);
2022-12-25 12:23:53 -05:00
Utils::Hook(0x497DB5, GetMapIndex, HOOK_CALL).install()->quick();
Utils::Hook(0x42A19D, MapNameCopy, HOOK_CALL).install()->quick();
Utils::Hook(0x4A6FEE, SetMapName, HOOK_CALL).install()->quick();
2017-01-19 16:23:59 -05:00
// Store playlist buffer on load
2022-12-25 12:23:53 -05:00
Utils::Hook(0x42961C, Com_ParseOnLine_Hk, HOOK_CALL).install()->quick(); // Playlist_ParsePlaylists
2017-01-19 16:23:59 -05:00
//if (Dedicated::IsDedicated())
{
// Custom playlist loading
2022-12-25 12:23:53 -05:00
Utils::Hook(0x420B5A, LoadPlaylist, HOOK_JUMP).install()->quick();
2017-01-19 16:23:59 -05:00
2022-12-25 12:23:53 -05:00
// disable playlist.ff loading function (Win_LoadPlaylistFastfile)
Utils::Hook::Set<std::uint8_t>(0x4D6E60, 0xC3);
2017-01-19 16:23:59 -05:00
}
2022-08-19 19:10:35 -04:00
Network::OnClientPacket("getPlaylist", PlaylistRequest);
2022-12-25 12:23:53 -05:00
Network::OnClientPacket("playlistResponse", PlaylistResponse);
2022-08-19 19:10:35 -04:00
Network::OnClientPacket("playlistInvalidPassword", PlaylistInvalidPassword);
2017-01-19 16:23:59 -05:00
}
}