More connection progress
This commit is contained in:
parent
e1b1a95b4b
commit
c898746026
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user