Add usermap support
This commit is contained in:
parent
6f2dbbe471
commit
c73896456f
@ -1,10 +1,12 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
#include "game/utils.hpp"
|
||||||
|
|
||||||
#include "party.hpp"
|
#include "party.hpp"
|
||||||
#include "network.hpp"
|
#include "network.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
|
#include "workshop.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
@ -12,6 +14,7 @@
|
|||||||
#include <utils/cryptography.hpp>
|
#include <utils/cryptography.hpp>
|
||||||
#include <utils/concurrency.hpp>
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace party
|
namespace party
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
@ -34,10 +37,13 @@ namespace party
|
|||||||
return server_queries;
|
return server_queries;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode)
|
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode,
|
||||||
|
const std::string& pub_id)
|
||||||
{
|
{
|
||||||
|
workshop::load_usermap_mod_if_needed(pub_id);
|
||||||
|
|
||||||
game::XSESSION_INFO info{};
|
game::XSESSION_INFO info{};
|
||||||
game::CL_ConnectFromLobby(0, &info, &addr, 1, 0, mapname.data(), gamemode.data(), nullptr);
|
game::CL_ConnectFromLobby(0, &info, &addr, 1, 0, mapname.data(), gamemode.data(), pub_id.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void launch_mode(const game::eModes mode)
|
void launch_mode(const game::eModes mode)
|
||||||
@ -51,11 +57,11 @@ namespace party
|
|||||||
}
|
}
|
||||||
|
|
||||||
void connect_to_lobby_with_mode(const game::netadr_t& addr, const game::eModes mode, const std::string& mapname,
|
void connect_to_lobby_with_mode(const game::netadr_t& addr, const game::eModes mode, const std::string& mapname,
|
||||||
const std::string& gametype, const bool was_retried = false)
|
const std::string& gametype, const std::string& pub_id, const bool was_retried = false)
|
||||||
{
|
{
|
||||||
if (game::Com_SessionMode_IsMode(mode))
|
if (game::Com_SessionMode_IsMode(mode))
|
||||||
{
|
{
|
||||||
connect_to_lobby(addr, mapname, gametype);
|
connect_to_lobby(addr, mapname, gametype, pub_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +69,7 @@ namespace party
|
|||||||
{
|
{
|
||||||
scheduler::once([=]
|
scheduler::once([=]
|
||||||
{
|
{
|
||||||
connect_to_lobby_with_mode(addr, mode, mapname, gametype, true);
|
connect_to_lobby_with_mode(addr, mode, mapname, gametype, pub_id, true);
|
||||||
}, scheduler::main, 5s);
|
}, scheduler::main, 5s);
|
||||||
|
|
||||||
launch_mode(mode);
|
launch_mode(mode);
|
||||||
@ -170,6 +176,10 @@ namespace party
|
|||||||
//const auto xuid = strtoull(info.get("xuid").data(), nullptr, 16);
|
//const auto xuid = strtoull(info.get("xuid").data(), nullptr, 16);
|
||||||
|
|
||||||
scheduler::once([=]
|
scheduler::once([=]
|
||||||
|
{
|
||||||
|
const auto publisher_id = workshop::get_usermap_publisher_id(mapname);
|
||||||
|
|
||||||
|
if (workshop::check_valid_publisher_id(mapname, publisher_id))
|
||||||
{
|
{
|
||||||
if (is_connecting_to_dedi)
|
if (is_connecting_to_dedi)
|
||||||
{
|
{
|
||||||
@ -177,7 +187,8 @@ namespace party
|
|||||||
}
|
}
|
||||||
|
|
||||||
//connect_to_session(target, hostname, xuid, mode);
|
//connect_to_session(target, hostname, xuid, mode);
|
||||||
connect_to_lobby_with_mode(target, mode, mapname, gametype);
|
connect_to_lobby_with_mode(target, mode, mapname, gametype, publisher_id);
|
||||||
|
}
|
||||||
}, scheduler::main);
|
}, scheduler::main);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
89
src/client/component/workshop.cpp
Normal file
89
src/client/component/workshop.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
#include "workshop.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
|
namespace workshop
|
||||||
|
{
|
||||||
|
const std::string get_usermap_publisher_id(const std::string& mapname)
|
||||||
|
{
|
||||||
|
const auto total_usermaps = *reinterpret_cast<unsigned int*>(0x1567B3580_g);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < total_usermaps; ++i)
|
||||||
|
{
|
||||||
|
const auto usermap_data = reinterpret_cast<game::workshop_data*>(0x1567B3588_g + (sizeof(game::workshop_data) * i));
|
||||||
|
if (usermap_data->folderName == mapname)
|
||||||
|
{
|
||||||
|
return usermap_data->publisherId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_valid_publisher_id(const std::string& mapname, const std::string& pub_id)
|
||||||
|
{
|
||||||
|
if (!game::DB_FileExists(mapname.data(), 0) && pub_id.empty())
|
||||||
|
{
|
||||||
|
game::Com_Error(0, "Can't find usermap: %s!\nMake sure you're subscribed to the workshop item.", mapname.data());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_usermap_mod_if_needed(const std::string& pub_id)
|
||||||
|
{
|
||||||
|
if (!game::isModLoaded() && !pub_id.empty())
|
||||||
|
{
|
||||||
|
game::loadMod(0, "usermaps", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
utils::hook::detour setup_server_map_hook;
|
||||||
|
|
||||||
|
void setup_server_map_stub(int localClientNum, const char* mapname, const char* gametype)
|
||||||
|
{
|
||||||
|
const auto publisher_id = get_usermap_publisher_id(mapname);
|
||||||
|
load_usermap_mod_if_needed(publisher_id);
|
||||||
|
|
||||||
|
setup_server_map_hook.invoke(localClientNum, mapname, gametype);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_workshop_item_stub(int type, const char* mapname, int a3)
|
||||||
|
{
|
||||||
|
const auto publisher_id = get_usermap_publisher_id(mapname);
|
||||||
|
const auto name = publisher_id.empty() ? mapname : publisher_id.data();
|
||||||
|
|
||||||
|
return utils::hook::invoke<bool>(0x1420D6380_g, type, name, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::workshop_data* load_usermap_stub(const char* mapname)
|
||||||
|
{
|
||||||
|
const auto publisher_id = get_usermap_publisher_id(mapname);
|
||||||
|
const auto name = publisher_id.empty() ? mapname : publisher_id.data();
|
||||||
|
|
||||||
|
return utils::hook::invoke<game::workshop_data*>(0x1420D5700_g, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public client_component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
setup_server_map_hook.create(0x14135CD20_g, setup_server_map_stub);
|
||||||
|
|
||||||
|
// Allow client to switch maps if server sends zone name instead of publisher id
|
||||||
|
utils::hook::call(0x14135CD84_g, has_workshop_item_stub);
|
||||||
|
utils::hook::call(0x14135CE48_g, load_usermap_stub);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(workshop::component)
|
8
src/client/component/workshop.hpp
Normal file
8
src/client/component/workshop.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace workshop
|
||||||
|
{
|
||||||
|
const std::string get_usermap_publisher_id(const std::string& mapname);
|
||||||
|
bool check_valid_publisher_id(const std::string& mapname, const std::string& pub_id);
|
||||||
|
void load_usermap_mod_if_needed(const std::string& pub_id);
|
||||||
|
}
|
@ -1584,6 +1584,31 @@ namespace game
|
|||||||
|
|
||||||
static_assert(sizeof(gentity_s) == 0x4F8);
|
static_assert(sizeof(gentity_s) == 0x4F8);
|
||||||
|
|
||||||
|
enum workshop_type
|
||||||
|
{
|
||||||
|
WORKSHOP_MOD = 0x1,
|
||||||
|
WORKSHOP_USERMAP = 0x2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct workshop_data
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
char folderName[32];
|
||||||
|
char publisherId[32];
|
||||||
|
char description[256];
|
||||||
|
char contentPathToZoneFiles[260];
|
||||||
|
char absolutePathContentFolder[260];
|
||||||
|
char absolutePathZoneFiles[260];
|
||||||
|
int unk; // 1
|
||||||
|
int unk2; // 0
|
||||||
|
unsigned int publisherIdInteger;
|
||||||
|
int unk3;
|
||||||
|
unsigned int unk4;
|
||||||
|
workshop_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(workshop_data) == 0x4C8);
|
||||||
|
|
||||||
union XAssetHeader
|
union XAssetHeader
|
||||||
{
|
{
|
||||||
/*PhysPreset* physPreset;
|
/*PhysPreset* physPreset;
|
||||||
|
@ -59,6 +59,8 @@ namespace game
|
|||||||
0x141420ED0, 0x1401D5FB0
|
0x141420ED0, 0x1401D5FB0
|
||||||
};
|
};
|
||||||
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x1413E9DA0, 0x14019F080};
|
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x1413E9DA0, 0x14019F080};
|
||||||
|
WEAK symbol<bool(const char* zoneName, int source)> DB_FileExists{0x141420B40};
|
||||||
|
WEAK symbol<void()> DB_ReleaseXAssets{0x1414247C0};
|
||||||
|
|
||||||
// Live
|
// Live
|
||||||
WEAK symbol<bool(uint64_t, int*, bool)> Live_GetConnectivityInformation{0x141E0C380};
|
WEAK symbol<bool(uint64_t, int*, bool)> Live_GetConnectivityInformation{0x141E0C380};
|
||||||
@ -81,6 +83,9 @@ namespace game
|
|||||||
// Unnamed
|
// Unnamed
|
||||||
WEAK symbol<const char* (const char* name)> CopyString{0x1422AC220, 0x14056BD70};
|
WEAK symbol<const char* (const char* name)> CopyString{0x1422AC220, 0x14056BD70};
|
||||||
|
|
||||||
|
WEAK symbol<bool()> isModLoaded{0x1420D5020};
|
||||||
|
WEAK symbol<void(int, const char*, int)> loadMod{0x1420D6930};
|
||||||
|
|
||||||
// Dvar
|
// Dvar
|
||||||
WEAK symbol<bool(const dvar_t* dvar)> Dvar_IsSessionModeBaseDvar{0x1422C23A0, 0x140576890};
|
WEAK symbol<bool(const dvar_t* dvar)> Dvar_IsSessionModeBaseDvar{0x1422C23A0, 0x140576890};
|
||||||
WEAK symbol<dvar_t*(const char* dvarName)> Dvar_FindVar{0x1422BCCD0, 0x140575540};
|
WEAK symbol<dvar_t*(const char* dvarName)> Dvar_FindVar{0x1422BCCD0, 0x140575540};
|
||||||
|
Loading…
Reference in New Issue
Block a user