More connection progress

This commit is contained in:
momo5502 2022-10-28 22:16:14 +02:00
parent e1b1a95b4b
commit c898746026
9 changed files with 237 additions and 7 deletions

View File

@ -179,6 +179,22 @@ namespace network
return addr;
}
bool are_addresses_equal(const game::netadr_t& a, const game::netadr_t& b)
{
if (a.type != b.type)
{
return false;
}
if (a.type != game::NA_RAWIP && a.type != game::NA_IP)
{
return true;
}
return a.port == b.port && *reinterpret_cast<const uint32_t*>(&a.ipv4.a) == *reinterpret_cast<const uint32_t*>(&
b.ipv4.a);
}
class component final : public component_interface
{
public:

View File

@ -14,4 +14,47 @@ namespace network
void send_data(const game::netadr_t& address, const std::string& data);
game::netadr_t address_from_string(const std::string& address);
bool are_addresses_equal(const game::netadr_t& a, const game::netadr_t& b);
}
inline bool operator==(const game::netadr_t& a, const game::netadr_t& b)
{
return network::are_addresses_equal(a, b); //
}
inline bool operator!=(const game::netadr_t& a, const game::netadr_t& b)
{
return !(a == b); //
}
namespace std
{
template <>
struct equal_to<game::netadr_t>
{
using result_type = bool;
bool operator()(const game::netadr_t& lhs, const game::netadr_t& rhs) const
{
return network::are_addresses_equal(lhs, rhs);
}
};
template <>
struct hash<game::netadr_t>
{
size_t operator()(const game::netadr_t& x) const noexcept
{
const auto type_hash = hash<uint32_t>()(x.type);
if (x.type != game::NA_IP && x.type != game::NA_RAWIP)
{
return type_hash;
}
return type_hash ^ hash<uint32_t>()(*reinterpret_cast<const uint32_t*>(&x.ipv4.a)) ^ hash<
uint16_t>()(x.port);
}
};
}

View File

@ -2,20 +2,98 @@
#include "loader/component_loader.hpp"
#include "network.hpp"
#include "scheduler.hpp"
#include "game/game.hpp"
#include "steam/steam.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
#include <utils/info_string.hpp>
#include <utils/cryptography.hpp>
#include <version.hpp>
namespace party
{
namespace
{
struct
{
game::netadr_t host{{}, {}, game::NA_BAD, {}};
std::string challenge{};
} connect_state{};
void connect_stub(const char* address)
{
auto addr = network::address_from_string(address);
const auto target = network::address_from_string(address);
if (target.type == game::NA_BAD)
{
return;
}
connect_state.host = target;
connect_state.challenge = utils::cryptography::random::get_challenge();
network::send(target, "getInfo", connect_state.challenge);
}
void connect_to_lobby(const game::netadr_t& addr, const std::string& mapname, const std::string& gamemode)
{
game::XSESSION_INFO info{};
game::CL_ConnectFromLobby(0, &info, &addr, 1, 0, "mp_nuketown_x", "tdm");
game::CL_ConnectFromLobby(0, &info, &addr, 1, 0, mapname.data(), gamemode.data());
}
void launch_mode(const game::eModes mode)
{
const auto* command = "";
switch (mode)
{
case game::MODE_CAMPAIGN:
command = "startCampaign;";
break;
case game::MODE_ZOMBIES:
command = "startZombies;";
break;
case game::MODE_MULTIPLAYER:
command = "startMultiplayer;";
break;
default:
return;
}
game::Cbuf_AddText(0, command);
}
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)
{
if (game::Com_SessionMode_IsMode(mode))
{
connect_to_lobby(addr, mapname, gametype);
return;
}
if (!was_retried)
{
scheduler::once([=]
{
connect_to_lobby_with_mode(addr, mode, mapname, gametype, true);
}, scheduler::main, 5s);
launch_mode(mode);
}
}
std::string get_dvar_string(const char* dvar_name)
{
const auto dvar = game::Dvar_FindVar(dvar_name);
if (!dvar)
{
return {};
}
return game::Dvar_GetString(dvar);
}
}
@ -26,10 +104,77 @@ namespace party
{
utils::hook::jump(0x141EE6030_g, connect_stub);
/*network::on("_pong", [](const game::netadr_t& source, const network::data_view& data)
network::on("getInfo", [](const game::netadr_t& target, const network::data_view& data)
{
});*/
utils::info_string info{};
info.set("challenge", std::string(data.begin(), data.end()));
info.set("gamename", "T7");
info.set("hostname", get_dvar_string("sv_hostname"));
info.set("gametype", get_dvar_string("g_gametype"));
//info.set("sv_motd", get_dvar_string("sv_motd"));
info.set("xuid", utils::string::va("%llX", steam::SteamUser()->GetSteamID().bits));
info.set("mapname", get_dvar_string("mapname"));
//info.set("isPrivate", get_dvar_string("g_password").empty() ? "0" : "1");
//info.set("clients", utils::string::va("%i", get_client_count()));
//info.set("bots", utils::string::va("%i", get_bot_count()));
//info.set("sv_maxclients", utils::string::va("%i", *game::mp::svs_numclients));
info.set("protocol", utils::string::va("%i", 1/*PROTOCOL*/));
info.set("playmode", utils::string::va("%i", game::Com_SessionMode_GetMode()));
//info.set("sv_running", utils::string::va("%i", get_dvar_bool("sv_running")));
//info.set("dedicated", utils::string::va("%i", get_dvar_bool("dedicated")));
info.set("shortversion", SHORTVERSION);
network::send(target, "infoResponse", info.build(), '\n');
});
network::on("infoResponse", [](const game::netadr_t& target, const network::data_view& data)
{
const utils::info_string info{data};
if (connect_state.host != target)
{
return;
}
if (info.get("challenge") != connect_state.challenge)
{
const auto str = "Invalid challenge.";
printf("%s\n", str);
return;
}
const auto gamename = info.get("gamename");
if (gamename != "T7"s)
{
const auto str = "Invalid gamename.";
printf("%s\n", str);
return;
}
const auto mapname = info.get("mapname");
if (mapname.empty())
{
const auto str = "Invalid map.";
printf("%s\n", str);
return;
}
const auto gametype = info.get("gametype");
if (gametype.empty())
{
const auto str = "Invalid gametype.";
printf("%s\n", str);
return;
}
const auto playmode = info.get("playmode");
const auto mode = game::eModes(std::atoi(playmode.data()));
scheduler::once([=]
{
connect_to_lobby_with_mode(target, mode, mapname, gametype);
}, scheduler::main);
});
}
};
}

View File

@ -25,7 +25,8 @@ namespace game
b[1] = '\n';
b += 2;
}
else if (source && source[0] == '^' && source[1] && source[1] != '^' && source[1] >= 48 && source[1] <= 64) // Q_IsColorString
else if (source && source[0] == '^' && source[1] && source[1] != '^' && source[1] >= 48 && source[1] <= 64)
// Q_IsColorString
{
i++;
}
@ -40,4 +41,9 @@ namespace game
*b = 0;
return static_cast<int>(b - target);
}
game::eModes Com_SessionMode_GetMode()
{
return game::eModes(*reinterpret_cast<uint32_t*>(0x1568EF7F4_g) << 28 >> 28);
}
}

View File

@ -8,6 +8,7 @@ namespace game
Com_Error_(__FILE__, __LINE__, code, fmt, ##__VA_ARGS__)
int Conbuf_CleanText(const char* source, char* target);
game::eModes Com_SessionMode_GetMode();
template <typename T>
class symbol

View File

@ -4,6 +4,17 @@
namespace game
{
#endif
enum eModes
{
MODE_ZOMBIES = 0x0,
MODE_MULTIPLAYER = 0x1,
MODE_CAMPAIGN = 0x2,
MODE_COUNT = 0x3,
MODE_INVALID = 0x3,
MODE_FIRST = 0x0,
};
enum bdLobbyErrorCode
{
BD_NO_ERROR = 0x0,

View File

@ -8,13 +8,14 @@
namespace game
{
// CL
WEAK symbol<void(int controllerIndex, XSESSION_INFO* hostInfo, netadr_t* addr, int numPublicSlots,
WEAK symbol<void(int controllerIndex, XSESSION_INFO* hostInfo, const netadr_t* addr, int numPublicSlots,
int numPrivateSlots, const char* mapname, const char* gametype)> CL_ConnectFromLobby
{0x14134C570_g};
// Com
WEAK symbol<void(int channel, unsigned int label, const char* fmt, ...)> Com_Printf{0x1421499C0_g};
WEAK symbol<void(const char* file, int line, int code, const char* fmt, ...)> Com_Error_{0x1420F8BD0_g};
WEAK symbol<bool(eModes mode)> Com_SessionMode_IsMode{0x1420F7DD0_g};
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x1420EC8B0_g};
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{

View File

@ -13,6 +13,12 @@ namespace utils
{
}
info_string::info_string(const std::basic_string_view<uint8_t>& buffer)
: info_string(std::string_view(reinterpret_cast<const char*>(buffer.data()), buffer.size()))
{
}
void info_string::set(const std::string& key, const std::string& value)
{
this->key_value_pairs_[key] = value;

View File

@ -11,6 +11,7 @@ namespace utils
info_string() = default;
info_string(const std::string& buffer);
info_string(const std::string_view& buffer);
info_string(const std::basic_string_view<uint8_t>& buffer);
void set(const std::string& key, const std::string& value);
std::string get(const std::string& key) const;