Playlists.

This commit is contained in:
momo5502 2016-01-02 02:28:09 +01:00
parent 66ef54791a
commit 9aec8b2a1b
11 changed files with 210 additions and 50 deletions

View File

@ -21,6 +21,7 @@ namespace Components
Loader::Register(new Console()); Loader::Register(new Console());
Loader::Register(new IPCPipe()); Loader::Register(new IPCPipe());
Loader::Register(new Network()); Loader::Register(new Network());
Loader::Register(new Playlist());
Loader::Register(new RawFiles()); Loader::Register(new RawFiles());
Loader::Register(new Renderer()); Loader::Register(new Renderer());
Loader::Register(new UIFeeder()); Loader::Register(new UIFeeder());

View File

@ -32,6 +32,7 @@ namespace Components
#include "Modules\IPCPipe.hpp" #include "Modules\IPCPipe.hpp"
#include "Modules\Network.hpp" #include "Modules\Network.hpp"
#include "Modules\Party.hpp" // Destroys the order, but requires network classes :D #include "Modules\Party.hpp" // Destroys the order, but requires network classes :D
#include "Modules\Playlist.hpp"
#include "Modules\RawFiles.hpp" #include "Modules\RawFiles.hpp"
#include "Modules\Renderer.hpp" #include "Modules\Renderer.hpp"
#include "Modules\UIFeeder.hpp" #include "Modules\UIFeeder.hpp"

View File

@ -129,11 +129,7 @@ namespace Components
callback(); callback();
} }
__asm Utils::Hook::Call<void>(0x5A8E80);
{
mov eax, 5A8E80h
call eax
}
} }
Dedicated::Dedicated() Dedicated::Dedicated()
@ -231,6 +227,13 @@ namespace Components
Dedicated::Heartbeat(); Dedicated::Heartbeat();
} }
}); });
// Wrap xstartprivatematch
Command::Add("lobby_start", [] (Command::Params params)
{
Playlist::LoadPlaylist();
Command::Execute("xstartprivatematch", false);
});
} }
} }

View File

@ -17,9 +17,15 @@ namespace Components
return id; return id;
} }
Network::Address Party::Target()
{
return Party::Container.Target;
}
void Party::Connect(Network::Address target) void Party::Connect(Network::Address target)
{ {
Party::Container.Valid = true; Party::Container.Valid = true;
Party::Container.AwaitingPlaylist = false;
Party::Container.JoinTime = Game::Com_Milliseconds(); Party::Container.JoinTime = Game::Com_Milliseconds();
Party::Container.Target = target; Party::Container.Target = target;
Party::Container.Challenge = Utils::VA("%X", Party::Container.JoinTime); Party::Container.Challenge = Utils::VA("%X", Party::Container.JoinTime);
@ -68,6 +74,26 @@ namespace Components
return Dvar::Register<int>(name, 1, 1, max, Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED | flag, description).Get<Game::dvar_t*>(); return Dvar::Register<int>(name, 1, 1, max, Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED | flag, description).Get<Game::dvar_t*>();
} }
bool Party::PlaylistAwaiting()
{
return Party::Container.AwaitingPlaylist;
}
void Party::PlaylistContinue()
{
Party::Container.AwaitingPlaylist = false;
SteamID id = Party::GenerateLobbyId();
Party::LobbyMap[id.Bits] = Party::Container.Target;
Game::Steam_JoinLobby(id, 0);
// Callback not registered on first try
// TODO: Fix :D
if (Party::LobbyMap.size() <= 1) Game::Steam_JoinLobby(id, 0);
}
Party::Party() Party::Party()
{ {
// various changes to SV_DirectConnect-y stuff to allow non-party joinees // various changes to SV_DirectConnect-y stuff to allow non-party joinees
@ -126,13 +152,23 @@ namespace Components
Renderer::OnFrame([] () Renderer::OnFrame([] ()
{ {
if (!Party::Container.Valid) return; if (Party::Container.Valid)
{
if ((Game::Com_Milliseconds() - Party::Container.JoinTime) > 5000) if ((Game::Com_Milliseconds() - Party::Container.JoinTime) > 5000)
{ {
Party::Container.Valid = false; Party::Container.Valid = false;
Party::ConnectError("Server connection timed out."); Party::ConnectError("Server connection timed out.");
} }
}
if (Party::Container.AwaitingPlaylist)
{
if ((Game::Com_Milliseconds() - Party::Container.RequestTime) > 5000)
{
Party::Container.AwaitingPlaylist = false;
Party::ConnectError("Playlist request timed out.");
}
}
}); });
// Basic info handler // Basic info handler
@ -219,15 +255,10 @@ namespace Components
// Connect // Connect
else if (matchType == 1) // Party else if (matchType == 1) // Party
{ {
SteamID id = Party::GenerateLobbyId(); // Send playlist request
Party::Container.RequestTime = Game::Com_Milliseconds();
Party::LobbyMap[id.Bits] = address; Party::Container.AwaitingPlaylist = true;
Network::Send(address, "getplaylist\n");
Game::Steam_JoinLobby(id, 0);
// Callback not registered on first try
// TODO: Fix :D
if (Party::LobbyMap.size() <= 1) Game::Steam_JoinLobby(id, 0);
} }
else if (matchType == 2) // Match else if (matchType == 2) // Match
{ {

View File

@ -7,10 +7,14 @@ namespace Components
~Party(); ~Party();
const char* GetName() { return "Party"; }; const char* GetName() { return "Party"; };
static Network::Address Target();
static void Connect(Network::Address target); static void Connect(Network::Address target);
static const char* GetLobbyInfo(SteamID lobby, std::string key); static const char* GetLobbyInfo(SteamID lobby, std::string key);
static void RemoveLobby(SteamID lobby); static void RemoveLobby(SteamID lobby);
static bool PlaylistAwaiting();
static void PlaylistContinue();
private: private:
struct JoinContainer struct JoinContainer
{ {
@ -18,6 +22,10 @@ namespace Components
std::string Challenge; std::string Challenge;
DWORD JoinTime; DWORD JoinTime;
bool Valid; bool Valid;
// Party-specific stuff
DWORD RequestTime;
bool AwaitingPlaylist;
}; };
static JoinContainer Container; static JoinContainer Container;

View File

@ -0,0 +1,119 @@
#include "..\..\STDInclude.hpp"
namespace Components
{
std::string Playlist::CurrentPlaylistBuffer;
void Playlist::LoadPlaylist()
{
// Check if playlist already loaded
if (Utils::Hook::Get<bool>(0x1AD3680)) return;
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;
//return Utils::Hook::Call<DWORD>(0x4C0350);
__asm
{
push buffer
mov eax, 4C0350h
call eax
add esp, 4h
}
}
void Playlist::PlaylistRequest(Network::Address address, std::string data)
{
Logger::Print("Received playlist request, sending currently stored buffer.\n");
Network::Send(address, std::string("playlistresponse\n") + Playlist::CurrentPlaylistBuffer);
}
void Playlist::PlaylistReponse(Network::Address address, std::string data)
{
if (Party::PlaylistAwaiting())
{
if (address == Party::Target())
{
Logger::Print("Received playlist response, loading and continuing connection.\n");
Game::Live_ParsePlaylists(data.data());
Party::PlaylistContinue();
}
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()
{
// Apply new playlist
char* playlist = "mp_playlists_dlc2";
Utils::Hook::Set<char*>(0x494803, playlist);
Utils::Hook::Set<char*>(0x4C6EC1, playlist);
Utils::Hook::Set<char*>(0x4CF7F9, playlist);
Utils::Hook::Set<char*>(0x4D6E63, playlist);
Utils::Hook::Set<char*>(0x4D7358, playlist);
Utils::Hook::Set<char*>(0x4D73C8, playlist);
Utils::Hook::Set<char*>(0x4F4EA1, playlist);
Utils::Hook::Set<char*>(0x4D47FB, "mp_playlists_dlc2.ff");
Utils::Hook::Set<char*>(0x60B06E, "playlists.patch2");
// 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
Utils::Hook::Set<BYTE>(0x5B69E9, 0xEB);// too new
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();
if (Dedicated::IsDedicated())
{
// 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();
}
}

View File

@ -0,0 +1,22 @@
namespace Components
{
class Playlist : public Component
{
public:
typedef void(*Callback)();
Playlist();
~Playlist();
const char* GetName() { return "Playlist"; };
static void LoadPlaylist();
private:
static std::string CurrentPlaylistBuffer;
static DWORD StorePlaylistStub(const char** buffer);
static void PlaylistRequest(Network::Address address, std::string data);
static void PlaylistReponse(Network::Address address, std::string data);
};
}

View File

@ -28,35 +28,6 @@ namespace Components
Utils::Hook::Nop(0x451145, 5); Utils::Hook::Nop(0x451145, 5);
Utils::Hook::Set<BYTE>(0x45114C, 0xEB); Utils::Hook::Set<BYTE>(0x45114C, 0xEB);
// Apply new playlist
char* playlist = "mp_playlists_dlc2";
Utils::Hook::Set<char*>(0x494803, playlist);
Utils::Hook::Set<char*>(0x4C6EC1, playlist);
Utils::Hook::Set<char*>(0x4CF7F9, playlist);
Utils::Hook::Set<char*>(0x4D6E63, playlist);
Utils::Hook::Set<char*>(0x4D7358, playlist);
Utils::Hook::Set<char*>(0x4D73C8, playlist);
Utils::Hook::Set<char*>(0x4F4EA1, playlist);
Utils::Hook::Set<char*>(0x4D47FB, "mp_playlists_dlc2.ff");
Utils::Hook::Set<char*>(0x60B06E, "playlists.patch2");
// disable playlist download function
Utils::Hook::Set<BYTE>(0x4D4790, 0xC3);
// disable playlist.ff loading function
//Utils::Hook::Set<BYTE>(0x4D6E60, 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);
//Got playlists is true
//Utils::Hook::Set<bool>(0x1AD3680, true);
// LSP disabled // LSP disabled
Utils::Hook::Set<BYTE>(0x435950, 0xC3); // LSP HELLO Utils::Hook::Set<BYTE>(0x435950, 0xC3); // LSP HELLO
Utils::Hook::Set<BYTE>(0x49C220, 0xC3); // We wanted to send a logging packet, but we haven't connected to LSP! Utils::Hook::Set<BYTE>(0x49C220, 0xC3); // We wanted to send a logging packet, but we haven't connected to LSP!

View File

@ -65,6 +65,7 @@ namespace Game
NET_StringToAdr_t NET_StringToAdr = (NET_StringToAdr_t)0x409010; NET_StringToAdr_t NET_StringToAdr = (NET_StringToAdr_t)0x409010;
Live_MPAcceptInvite_t Live_MPAcceptInvite = (Live_MPAcceptInvite_t)0x420A6D; Live_MPAcceptInvite_t Live_MPAcceptInvite = (Live_MPAcceptInvite_t)0x420A6D;
Live_ParsePlaylists_t Live_ParsePlaylists = (Live_ParsePlaylists_t)0x4295A0;
LoadInitialFF_t LoadInitialFF = (LoadInitialFF_t)0x506AC0; LoadInitialFF_t LoadInitialFF = (LoadInitialFF_t)0x506AC0;
LoadModdableRawfile_t LoadModdableRawfile = (LoadModdableRawfile_t)0x61ABC0; LoadModdableRawfile_t LoadModdableRawfile = (LoadModdableRawfile_t)0x61ABC0;

View File

@ -151,6 +151,9 @@ namespace Game
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;
typedef void(__cdecl * Live_ParsePlaylists_t)(const char* data);
extern Live_ParsePlaylists_t Live_ParsePlaylists;
typedef void(*LoadInitialFF_t)(void); typedef void(*LoadInitialFF_t)(void);
extern LoadInitialFF_t LoadInitialFF; extern LoadInitialFF_t LoadInitialFF;

View File

@ -1,7 +1,7 @@
#include "..\STDInclude.hpp" #include "..\STDInclude.hpp"
#define VA_BUFFER_COUNT 4 #define VA_BUFFER_COUNT 4
#define VA_BUFFER_SIZE 4096 #define VA_BUFFER_SIZE 65536
namespace Utils namespace Utils
{ {
@ -13,7 +13,7 @@ namespace Utils
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
char* dest = g_vaBuffer[g_vaNextBufferIndex]; char* dest = g_vaBuffer[g_vaNextBufferIndex];
vsprintf_s(g_vaBuffer[g_vaNextBufferIndex], fmt, ap); vsnprintf(g_vaBuffer[g_vaNextBufferIndex], VA_BUFFER_SIZE, fmt, ap);
g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT; g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT;
va_end(ap); va_end(ap);
return dest; return dest;