2016-01-04 14:58:00 -05:00
|
|
|
#include "STDInclude.hpp"
|
2016-01-01 20:28:09 -05:00
|
|
|
|
|
|
|
namespace Components
|
|
|
|
{
|
|
|
|
std::string Playlist::CurrentPlaylistBuffer;
|
2016-01-03 09:14:44 -05:00
|
|
|
std::string Playlist::ReceivedPlaylistBuffer;
|
2016-01-01 20:28:09 -05:00
|
|
|
|
|
|
|
void Playlist::LoadPlaylist()
|
|
|
|
{
|
|
|
|
// Check if playlist already loaded
|
|
|
|
if (Utils::Hook::Get<bool>(0x1AD3680)) return;
|
|
|
|
|
2016-01-08 08:24:05 -05:00
|
|
|
// Don't load playlists when dedi and no party
|
|
|
|
if (Dedicated::IsDedicated() && !Dvar::Var("party_enable").Get<bool>())
|
|
|
|
{
|
|
|
|
Utils::Hook::Set<bool>(0x1AD3680, true); // Set received to true
|
|
|
|
Dvar::Var("xblive_privateserver").Set(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Dvar::Var("xblive_privateserver").Set(false);
|
|
|
|
|
2016-01-01 20:28:09 -05:00
|
|
|
std::string playlistFilename = Dvar::Var("playlistFilename").Get<char*>();
|
|
|
|
FileSystem::File playlist(playlistFilename);
|
|
|
|
|
|
|
|
if (playlist.Exists())
|
|
|
|
{
|
|
|
|
Logger::Print("Parsing playlist '%s'...\n", playlist.GetName().data());
|
|
|
|
Game::Live_ParsePlaylists(playlist.GetBuffer().data());
|
|
|
|
Utils::Hook::Set<bool>(0x1AD3680, true); // Playlist loaded
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Logger::Print("Unable to load playlist '%s'!\n", playlist.GetName().data());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD Playlist::StorePlaylistStub(const char** buffer)
|
|
|
|
{
|
|
|
|
Playlist::CurrentPlaylistBuffer = *buffer;
|
2016-01-01 20:47:15 -05:00
|
|
|
return Utils::Hook::Call<DWORD(const char**)>(0x4C0350)(buffer);
|
2016-01-01 20:28:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void Playlist::PlaylistRequest(Network::Address address, std::string data)
|
|
|
|
{
|
|
|
|
Logger::Print("Received playlist request, sending currently stored buffer.\n");
|
2016-01-03 09:14:44 -05:00
|
|
|
|
|
|
|
// Split playlist data
|
2016-01-03 13:28:47 -05:00
|
|
|
unsigned int maxPacketSize = 1000;
|
2016-01-03 09:14:44 -05:00
|
|
|
unsigned int maxBytes = Playlist::CurrentPlaylistBuffer.size();
|
|
|
|
|
2016-01-03 12:07:23 -05:00
|
|
|
for (unsigned int i = 0; i < maxBytes; i += maxPacketSize)
|
2016-01-03 09:14:44 -05:00
|
|
|
{
|
2016-01-03 12:07:23 -05:00
|
|
|
unsigned int sendBytes = min(maxPacketSize, maxBytes - i);
|
2016-01-03 09:14:44 -05:00
|
|
|
unsigned int sentBytes = i + sendBytes;
|
|
|
|
|
|
|
|
std::string data;
|
|
|
|
data.append(reinterpret_cast<char*>(&sentBytes), 4); // Sent bytes
|
|
|
|
data.append(reinterpret_cast<char*>(&maxBytes), 4); // Max bytes
|
|
|
|
|
|
|
|
data.append(Playlist::CurrentPlaylistBuffer.data() + i, sendBytes);
|
|
|
|
|
|
|
|
Network::SendRaw(address, std::string("playlistresponse\n") + data);
|
|
|
|
}
|
2016-01-01 20:28:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void Playlist::PlaylistReponse(Network::Address address, std::string data)
|
|
|
|
{
|
|
|
|
if (Party::PlaylistAwaiting())
|
|
|
|
{
|
|
|
|
if (address == Party::Target())
|
|
|
|
{
|
2016-01-03 09:14:44 -05:00
|
|
|
if (data.size() <= 8)
|
|
|
|
{
|
|
|
|
Party::PlaylistError(Utils::VA("Received playlist response, but it is invalid."));
|
|
|
|
Playlist::ReceivedPlaylistBuffer.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned int sentBytes = *(unsigned int*)(data.data() + 0);
|
|
|
|
unsigned int maxBytes = *(unsigned int*)(data.data() + 4);
|
|
|
|
|
|
|
|
// Clear current buffer, if we receive a new packet
|
|
|
|
if (data.size() - 8 == sentBytes) Playlist::ReceivedPlaylistBuffer.clear();
|
|
|
|
|
|
|
|
// Append received data
|
|
|
|
Playlist::ReceivedPlaylistBuffer.append(data.data() + 8, data.size() - 8);
|
|
|
|
|
|
|
|
if (Playlist::ReceivedPlaylistBuffer.size() != sentBytes)
|
|
|
|
{
|
|
|
|
Party::PlaylistError(Utils::VA("Received playlist data, but it seems invalid: %d != %d", sentBytes, Playlist::ReceivedPlaylistBuffer.size()));
|
|
|
|
Playlist::ReceivedPlaylistBuffer.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Logger::Print("Received playlist data: %d/%d (%d%%)\n", sentBytes, maxBytes, ((100 * sentBytes) / maxBytes));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Playlist::ReceivedPlaylistBuffer.size() == maxBytes)
|
|
|
|
{
|
2016-01-04 05:32:05 -05:00
|
|
|
Logger::Print("Received playlist, loading and continuing connection...\n");
|
2016-01-03 09:14:44 -05:00
|
|
|
Game::Live_ParsePlaylists(Playlist::ReceivedPlaylistBuffer.data());
|
|
|
|
Party::PlaylistContinue();
|
|
|
|
|
|
|
|
Playlist::ReceivedPlaylistBuffer.clear();
|
|
|
|
}
|
|
|
|
}
|
2016-01-01 20:28:09 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Logger::Print("Received playlist from someone else than our target host, ignoring it.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Logger::Print("Received stray playlist response, ignoring it.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Playlist::Playlist()
|
|
|
|
{
|
2016-01-02 20:37:06 -05:00
|
|
|
// Default playlists
|
|
|
|
Utils::Hook::Set<char*>(0x60B06E, "playlists_default.info");
|
2016-01-01 20:28:09 -05:00
|
|
|
|
|
|
|
// disable playlist download function
|
|
|
|
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);
|
|
|
|
|
|
|
|
// playlist dvar 'validity check'
|
|
|
|
Utils::Hook::Set<BYTE>(0x4B1170, 0xC3);
|
|
|
|
|
|
|
|
// disable playlist checking
|
2016-01-01 22:51:08 -05:00
|
|
|
Utils::Hook::Set<BYTE>(0x5B69E9, 0xEB); // too new
|
2016-01-01 20:28:09 -05:00
|
|
|
Utils::Hook::Set<BYTE>(0x5B696E, 0xEB); // too old
|
|
|
|
|
|
|
|
//Got playlists is true
|
|
|
|
//Utils::Hook::Set<bool>(0x1AD3680, true);
|
|
|
|
|
|
|
|
// Store playlist buffer on load
|
|
|
|
Utils::Hook(0x42961C, Playlist::StorePlaylistStub, HOOK_CALL).Install()->Quick();
|
|
|
|
|
2016-01-02 20:37:06 -05:00
|
|
|
//if (Dedicated::IsDedicated())
|
2016-01-01 20:28:09 -05:00
|
|
|
{
|
|
|
|
// Custom playlist loading
|
|
|
|
Utils::Hook(0x420B5A, Playlist::LoadPlaylist, HOOK_JUMP).Install()->Quick();
|
|
|
|
|
|
|
|
// disable playlist.ff loading function
|
|
|
|
Utils::Hook::Set<BYTE>(0x4D6E60, 0xC3);
|
|
|
|
}
|
|
|
|
|
|
|
|
Network::Handle("getplaylist", PlaylistRequest);
|
|
|
|
Network::Handle("playlistresponse", PlaylistReponse);
|
|
|
|
}
|
|
|
|
|
|
|
|
Playlist::~Playlist()
|
|
|
|
{
|
|
|
|
Playlist::CurrentPlaylistBuffer.clear();
|
2016-01-03 09:14:44 -05:00
|
|
|
Playlist::ReceivedPlaylistBuffer.clear();
|
2016-01-01 20:28:09 -05:00
|
|
|
}
|
|
|
|
}
|