connect experiments
This commit is contained in:
parent
40b13cea35
commit
cbb1982bb3
246
src/client/component/network.cpp
Normal file
246
src/client/component/network.cpp
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "network.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include "console.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
|
namespace network
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, callback>& get_callbacks()
|
||||||
|
{
|
||||||
|
static std::unordered_map<std::string, callback> callbacks{};
|
||||||
|
return callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on(const std::string& command, const callback& callback)
|
||||||
|
{
|
||||||
|
get_callbacks()[utils::string::to_lower(command)] = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handle_command(game::netadr_s* address, const char* command, game::msg_t* message)
|
||||||
|
{
|
||||||
|
const auto cmd_string = utils::string::to_lower(command);
|
||||||
|
auto& callbacks = get_callbacks();
|
||||||
|
const auto handler = callbacks.find(cmd_string);
|
||||||
|
const auto offset = cmd_string.size() + 5;
|
||||||
|
if (message->cursize < offset || handler == callbacks.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string_view data(message->data + offset, message->cursize - offset);
|
||||||
|
|
||||||
|
handler->second(*address, data);
|
||||||
|
#ifdef DEBUG
|
||||||
|
console::info("[Network] Handling command %s\n", cmd_string.data());
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
utils::hook::detour cl_main_connectionless_packet_universal_hook;
|
||||||
|
bool cl_main_connectionless_packet_universal_stub(int client_num, game::netadr_s* from, game::msg_t* msg, int time, const char* c)
|
||||||
|
{
|
||||||
|
if (handle_command(from, c, msg))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cl_main_connectionless_packet_universal_hook.invoke<bool>(client_num, from, msg, time, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_send_packet_stub(const int size, const char* src, game::netadr_s* to)
|
||||||
|
{
|
||||||
|
if (to->type == game::NA_BROADCAST || to->type == game::NA_IP)
|
||||||
|
{
|
||||||
|
if (*game::query_socket)
|
||||||
|
{
|
||||||
|
sockaddr s = {};
|
||||||
|
game::NetadrToSockadr(to, &s);
|
||||||
|
return sendto(*game::query_socket, src, size, 0, &s, 16) >= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
game::Com_Error(game::ERR_DROP, "Sys_SendPacket: bad address type %i", to->type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_compare_base_address(const game::netadr_s* a, const game::netadr_s* b)
|
||||||
|
{
|
||||||
|
if (a->type == b->type)
|
||||||
|
{
|
||||||
|
switch (a->type)
|
||||||
|
{
|
||||||
|
case game::netadrtype_t::NA_BOT:
|
||||||
|
case game::netadrtype_t::NA_LOOPBACK:
|
||||||
|
return a->port == b->port;
|
||||||
|
|
||||||
|
case game::netadrtype_t::NA_IP:
|
||||||
|
return !memcmp(a->ip, b->ip, 4);
|
||||||
|
case game::netadrtype_t::NA_BROADCAST:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console::warn("NET_CompareBaseAdr: bad address type\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_compare_address(const game::netadr_s* a, const game::netadr_s* b)
|
||||||
|
{
|
||||||
|
return net_compare_base_address(a, b) && a->port == b->port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(const game::netadr_s& address, const std::string& command, const std::string& data, const char separator)
|
||||||
|
{
|
||||||
|
std::string packet = "\xFF\xFF\xFF\xFF";
|
||||||
|
packet.append(command);
|
||||||
|
packet.push_back(separator);
|
||||||
|
packet.append(data);
|
||||||
|
|
||||||
|
send_data(address, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_data(const game::netadr_s& address, const std::string& data)
|
||||||
|
{
|
||||||
|
auto size = static_cast<int>(data.size());
|
||||||
|
if (address.type == game::NA_LOOPBACK)
|
||||||
|
{
|
||||||
|
// TODO: Fix this for loopback
|
||||||
|
if (size > 1280)
|
||||||
|
{
|
||||||
|
console::error("Packet was too long. Truncated!\n");
|
||||||
|
size = 1280;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::NET_SendLoopPacket(game::NS_CLIENT1, size, data.data(), &address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
game::Sys_SendPacket(size, data.data(), &address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool are_addresses_equal(const game::netadr_s& a, const game::netadr_s& b)
|
||||||
|
{
|
||||||
|
return net_compare_address(&a, &b);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* net_adr_to_string(const game::netadr_s& a)
|
||||||
|
{
|
||||||
|
if (a.type == game::netadrtype_t::NA_LOOPBACK)
|
||||||
|
{
|
||||||
|
return "loopback";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.type == game::netadrtype_t::NA_BOT)
|
||||||
|
{
|
||||||
|
return "bot";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.type == game::netadrtype_t::NA_IP || a.type == game::netadrtype_t::NA_BROADCAST)
|
||||||
|
{
|
||||||
|
if (a.port)
|
||||||
|
{
|
||||||
|
return utils::string::va("%u.%u.%u.%u:%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3], htons(a.port));
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils::string::va("%u.%u.%u.%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "bad";
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
// redirect packet sends to our stub
|
||||||
|
utils::hook::jump(game::Sys_SendPacket, sys_send_packet_stub);
|
||||||
|
|
||||||
|
// intercept command handling
|
||||||
|
cl_main_connectionless_packet_universal_hook.create(0x9B06E0_b, cl_main_connectionless_packet_universal_stub);
|
||||||
|
|
||||||
|
// handle xuid without secure connection
|
||||||
|
utils::hook::nop(0xC53315_b, 2);
|
||||||
|
|
||||||
|
utils::hook::jump(game::NET_CompareAdr, net_compare_address);
|
||||||
|
utils::hook::jump(game::NET_CompareBaseAdr, net_compare_base_address);
|
||||||
|
|
||||||
|
// don't establish secure conenction
|
||||||
|
utils::hook::set<uint8_t>(0x9DBFDD_b, 0xEB);
|
||||||
|
utils::hook::set<uint8_t>(0x9DC47D_b, 0xEB);
|
||||||
|
utils::hook::set<uint8_t>(0x9DDC79_b, 0xEB);
|
||||||
|
|
||||||
|
// ignore unregistered connection
|
||||||
|
utils::hook::jump(0xC4F200_b, 0xC4F1AB_b);
|
||||||
|
utils::hook::jump(0xC4F2F6_b, 0xC4F399_b);
|
||||||
|
|
||||||
|
// disable xuid verification
|
||||||
|
//utils::hook::set<uint8_t>(0x728BF_b, 0xEB);
|
||||||
|
|
||||||
|
// ignore configstring mismatch
|
||||||
|
utils::hook::set<uint8_t>(0x9B6F91_b, 0xEB);
|
||||||
|
|
||||||
|
// ignore dw handle in SvClientMP::FindClientAtAddress
|
||||||
|
utils::hook::set<uint8_t>(0xC58B2B_b, 0xEB);
|
||||||
|
|
||||||
|
// ignore dw handle in SV_DirectConnect
|
||||||
|
utils::hook::set<uint8_t>(0xC4EE1A_b, 0xEB);
|
||||||
|
utils::hook::set<uint8_t>(0xC4F0FB_b, 0xEB);
|
||||||
|
|
||||||
|
// increase cl_maxpackets
|
||||||
|
//dvars::override::register_int("cl_maxpackets", 1000, 1, 1000, game::DVAR_FLAG_SAVED);
|
||||||
|
|
||||||
|
// increase snaps
|
||||||
|
//dvars::override::register_int("sv_remote_client_snapshot_msec", 33, 33, 100, game::DVAR_FLAG_NONE);
|
||||||
|
|
||||||
|
// ignore impure client
|
||||||
|
utils::hook::jump(0xC500C8_b, 0xC500DE_b); // maybe add sv_pure dvar?
|
||||||
|
|
||||||
|
// don't send checksum
|
||||||
|
//utils::hook::set<uint8_t>(0x0, 0);
|
||||||
|
|
||||||
|
// don't read checksum
|
||||||
|
utils::hook::set(0xCE6E60_b, 0xC301B0);
|
||||||
|
|
||||||
|
// don't try to reconnect client
|
||||||
|
//utils::hook::call(0x0, reconnect_migratated_client);
|
||||||
|
//utils::hook::nop(0x0, 4); // this crashes when reconnecting for some reason
|
||||||
|
|
||||||
|
// increase allowed packet size
|
||||||
|
//const auto max_packet_size = 0x20000;
|
||||||
|
//utils::hook::set<int>(0x0, max_packet_size);
|
||||||
|
//utils::hook::set<int>(0x0, max_packet_size);
|
||||||
|
//utils::hook::set<int>(0x0, max_packet_size);
|
||||||
|
//utils::hook::set<int>(0x0, max_packet_size);
|
||||||
|
|
||||||
|
// ignore built in "print" oob command and add in our own
|
||||||
|
utils::hook::set<uint8_t>(0x9B0326_b, 0xEB);
|
||||||
|
network::on("print", [](const game::netadr_s&, const std::string_view& data)
|
||||||
|
{
|
||||||
|
const std::string message{ data };
|
||||||
|
console::info(message.data());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use our own socket since the game's socket doesn't work with non localhost addresses
|
||||||
|
// why? no idea
|
||||||
|
//utils::hook::jump(0x0, create_socket);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(network::component)
|
48
src/client/component/network.hpp
Normal file
48
src/client/component/network.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
namespace network
|
||||||
|
{
|
||||||
|
using callback = std::function<void(const game::netadr_s&, const std::string_view&)>;
|
||||||
|
|
||||||
|
void on(const std::string& command, const callback& callback);
|
||||||
|
void send(const game::netadr_s& address, const std::string& command, const std::string& data = {}, char separator = ' ');
|
||||||
|
void send_data(const game::netadr_s& address, const std::string& data);
|
||||||
|
|
||||||
|
bool are_addresses_equal(const game::netadr_s& a, const game::netadr_s& b);
|
||||||
|
|
||||||
|
const char* net_adr_to_string(const game::netadr_s& a);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const game::netadr_s& a, const game::netadr_s& b)
|
||||||
|
{
|
||||||
|
return network::are_addresses_equal(a, b); //
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const game::netadr_s& a, const game::netadr_s& b)
|
||||||
|
{
|
||||||
|
return !(a == b); //
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
struct equal_to<game::netadr_s>
|
||||||
|
{
|
||||||
|
using result_type = bool;
|
||||||
|
|
||||||
|
bool operator()(const game::netadr_s& lhs, const game::netadr_s& rhs) const
|
||||||
|
{
|
||||||
|
return network::are_addresses_equal(lhs, rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<game::netadr_s>
|
||||||
|
{
|
||||||
|
size_t operator()(const game::netadr_s& x) const noexcept
|
||||||
|
{
|
||||||
|
return hash<uint32_t>()(*reinterpret_cast<const uint32_t*>(&x.ip[0])) ^ hash<uint16_t>()(x.port);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
242
src/client/component/party.cpp
Normal file
242
src/client/component/party.cpp
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "party.hpp"
|
||||||
|
|
||||||
|
#include "steam/steam.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include "command.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
#include "network.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/info_string.hpp>
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/cryptography.hpp>
|
||||||
|
|
||||||
|
namespace party
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
game::netadr_s host{};
|
||||||
|
std::string challenge{};
|
||||||
|
bool hostDefined{ false };
|
||||||
|
} connect_state;
|
||||||
|
|
||||||
|
void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype)
|
||||||
|
{
|
||||||
|
if (game::Com_GameMode_GetActiveGameMode() != game::GAME_MODE_MP &&
|
||||||
|
game::Com_GameMode_GetActiveGameMode() != game::GAME_MODE_CP)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (game::Live_SyncOnlineDataFlags(0) != 0)
|
||||||
|
{
|
||||||
|
// initialize the game after onlinedataflags is 32 (workaround)
|
||||||
|
if (game::Live_SyncOnlineDataFlags(0) == 32)
|
||||||
|
{
|
||||||
|
scheduler::once([=]()
|
||||||
|
{
|
||||||
|
command::execute("xstartprivateparty", true);
|
||||||
|
command::execute("disconnect", true); // 32 -> 0
|
||||||
|
|
||||||
|
connect_to_party(target, mapname, gametype);
|
||||||
|
}, scheduler::pipeline::main, 1s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scheduler::once([=]()
|
||||||
|
{
|
||||||
|
connect_to_party(target, mapname, gametype);
|
||||||
|
}, scheduler::pipeline::main, 1s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//perform_game_initialization();
|
||||||
|
|
||||||
|
// shutdown frontend
|
||||||
|
game::Com_FrontEndScene_ShutdownAndDisable();
|
||||||
|
|
||||||
|
// connect
|
||||||
|
char session_info[0x100] = {};
|
||||||
|
game::CL_MainMP_ConnectAndPreloadMap(0, reinterpret_cast<void*>(session_info), &target, mapname.data(), gametype.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_dvar_string(const std::string& dvar)
|
||||||
|
{
|
||||||
|
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||||
|
if (dvar_value && dvar_value->current.string)
|
||||||
|
{
|
||||||
|
return dvar_value->current.string;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_dvar_int(const std::string& dvar)
|
||||||
|
{
|
||||||
|
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||||
|
if (dvar_value && dvar_value->current.integer)
|
||||||
|
{
|
||||||
|
return dvar_value->current.integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_dvar_bool(const std::string& dvar)
|
||||||
|
{
|
||||||
|
auto* dvar_value = game::Dvar_FindVar(dvar.data());
|
||||||
|
if (dvar_value && dvar_value->current.enabled)
|
||||||
|
{
|
||||||
|
return dvar_value->current.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_client_count()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_bot_count()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect(const game::netadr_s& target)
|
||||||
|
{
|
||||||
|
//command::execute("lui_open_popup popup_acceptinginvite", false);
|
||||||
|
|
||||||
|
connect_state.host = target;
|
||||||
|
connect_state.challenge = utils::cryptography::random::get_challenge();
|
||||||
|
connect_state.hostDefined = true;
|
||||||
|
|
||||||
|
network::send(target, "getInfo", connect_state.challenge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void info_response_error(const std::string& error)
|
||||||
|
{
|
||||||
|
console::error("%s\n", error.data());
|
||||||
|
//if (game::Menu_IsMenuOpenAndVisible(0, "popup_acceptinginvite"))
|
||||||
|
//{
|
||||||
|
// command::execute("lui_close popup_acceptinginvite", false);
|
||||||
|
//}
|
||||||
|
|
||||||
|
game::Com_SetLocalizedErrorMessage(error.data(), "MENU_NOTICE");
|
||||||
|
//*reinterpret_cast<int*>(0x0) = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
command::add("connect", [](const command::params& argument)
|
||||||
|
{
|
||||||
|
if (argument.size() != 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::netadr_s target{};
|
||||||
|
if (game::NET_StringToAdr(argument[1], &target))
|
||||||
|
{
|
||||||
|
connect(target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
network::on("getInfo", [](const game::netadr_s& target, const std::string_view& data)
|
||||||
|
{
|
||||||
|
utils::info_string info{};
|
||||||
|
info.set("challenge", std::string{ data });
|
||||||
|
info.set("gamename", "IW7");
|
||||||
|
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::svs_numclients));
|
||||||
|
info.set("protocol", utils::string::va("%i", PROTOCOL));
|
||||||
|
info.set("playmode", utils::string::va("%i", game::Com_GameMode_GetActiveGameMode()));
|
||||||
|
info.set("sv_running", utils::string::va("%i", get_dvar_bool("sv_running") && !game::Com_FrontEndScene_IsActive()));
|
||||||
|
info.set("dedicated", utils::string::va("%i", get_dvar_bool("dedicated")));
|
||||||
|
|
||||||
|
network::send(target, "infoResponse", info.build(), '\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
network::on("infoResponse", [](const game::netadr_s& target, const std::string_view& data)
|
||||||
|
{
|
||||||
|
const utils::info_string info{ data };
|
||||||
|
//server_list::handle_info_response(target, info);
|
||||||
|
|
||||||
|
if (connect_state.host != target)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.get("challenge") != connect_state.challenge)
|
||||||
|
{
|
||||||
|
info_response_error("Invalid challenge.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto gamename = info.get("gamename");
|
||||||
|
if (gamename != "IW7"s)
|
||||||
|
{
|
||||||
|
info_response_error("Invalid gamename.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto playmode = info.get("playmode");
|
||||||
|
if (game::GameModeType(std::atoi(playmode.data())) != game::Com_GameMode_GetActiveGameMode())
|
||||||
|
{
|
||||||
|
info_response_error("Invalid playmode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto sv_running = info.get("sv_running");
|
||||||
|
if (!std::atoi(sv_running.data()))
|
||||||
|
{
|
||||||
|
info_response_error("Server not running.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto mapname = info.get("mapname");
|
||||||
|
if (mapname.empty())
|
||||||
|
{
|
||||||
|
info_response_error("Invalid map.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto gametype = info.get("gametype");
|
||||||
|
if (gametype.empty())
|
||||||
|
{
|
||||||
|
info_response_error("Connection failed: Invalid gametype.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//party::sv_motd = info.get("sv_motd");
|
||||||
|
//party::sv_maxclients = std::stoi(info.get("sv_maxclients"));
|
||||||
|
|
||||||
|
connect_to_party(target, mapname, gametype);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(party::component)
|
22
src/client/component/party.hpp
Normal file
22
src/client/component/party.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
namespace party
|
||||||
|
{
|
||||||
|
void menu_error(const std::string& error);
|
||||||
|
|
||||||
|
void reset_connect_state();
|
||||||
|
|
||||||
|
void connect(const game::netadr_s& target);
|
||||||
|
void start_map(const std::string& mapname, bool dev = false);
|
||||||
|
|
||||||
|
void clear_sv_motd();
|
||||||
|
game::netadr_s get_state_host();
|
||||||
|
std::string get_state_challenge();
|
||||||
|
int server_client_count();
|
||||||
|
|
||||||
|
int get_client_num_by_name(const std::string& name);
|
||||||
|
|
||||||
|
int get_client_count();
|
||||||
|
int get_bot_count();
|
||||||
|
}
|
@ -391,6 +391,22 @@ namespace game
|
|||||||
unsigned int addrHandleIndex;
|
unsigned int addrHandleIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct msg_t
|
||||||
|
{
|
||||||
|
int overflowed;
|
||||||
|
int readOnly;
|
||||||
|
char* data;
|
||||||
|
char* splitData;
|
||||||
|
int maxsize;
|
||||||
|
int cursize;
|
||||||
|
int splitSize;
|
||||||
|
int readcount;
|
||||||
|
int bit;
|
||||||
|
int lastEntityRef;
|
||||||
|
netsrc_t targetLocalNetID;
|
||||||
|
int useZlib;
|
||||||
|
};
|
||||||
|
|
||||||
namespace entity
|
namespace entity
|
||||||
{
|
{
|
||||||
struct entityState_t
|
struct entityState_t
|
||||||
|
@ -23,6 +23,8 @@ namespace game
|
|||||||
WEAK symbol<bool()> Com_IsAnyLocalServerStarting{ 0xBAD9C0 };
|
WEAK symbol<bool()> Com_IsAnyLocalServerStarting{ 0xBAD9C0 };
|
||||||
WEAK symbol<bool()> Com_IsAnyLocalServerRunning{ 0xBAD9A0 };
|
WEAK symbol<bool()> Com_IsAnyLocalServerRunning{ 0xBAD9A0 };
|
||||||
|
|
||||||
|
WEAK symbol<void(const char* localizedMessage, const char* localizedTitle)> Com_SetLocalizedErrorMessage{ 0xBAF300 };
|
||||||
|
|
||||||
WEAK symbol<void(const char* finalmsg)> Com_Shutdown{ 0xBAFEA0 };
|
WEAK symbol<void(const char* finalmsg)> Com_Shutdown{ 0xBAFEA0 };
|
||||||
|
|
||||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{ 0xB7C290 };
|
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{ 0xB7C290 };
|
||||||
@ -31,6 +33,9 @@ namespace game
|
|||||||
WEAK symbol<void(int localClientNum, const char* msg, int flags)> CG_Utils_GameMessage{ 0x1D7FC0 };
|
WEAK symbol<void(int localClientNum, const char* msg, int flags)> CG_Utils_GameMessage{ 0x1D7FC0 };
|
||||||
WEAK symbol<void(int localClientNum, const char* msg, int flags)> CG_Utils_BoldGameMessage{ 0x1D7F10 };
|
WEAK symbol<void(int localClientNum, const char* msg, int flags)> CG_Utils_BoldGameMessage{ 0x1D7F10 };
|
||||||
|
|
||||||
|
WEAK symbol<void(int localClientNum, void* hostInfo, const netadr_s* addr, const char* mapname, const char* gametype)>
|
||||||
|
CL_MainMP_ConnectAndPreloadMap{ 0x9AED80 };
|
||||||
|
|
||||||
WEAK symbol<void(int localClientNum, int andMask)> CL_Keys_RemoveCatcher{ 0x9A9B00 };
|
WEAK symbol<void(int localClientNum, int andMask)> CL_Keys_RemoveCatcher{ 0x9A9B00 };
|
||||||
|
|
||||||
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{ 0xB7D040 };
|
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{ 0xB7D040 };
|
||||||
@ -89,6 +94,13 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<Material* (const char* material)> Material_RegisterHandle{ 0xE11CE0 };
|
WEAK symbol<Material* (const char* material)> Material_RegisterHandle{ 0xE11CE0 };
|
||||||
|
|
||||||
|
WEAK symbol<void(netadr_s*, sockaddr*)> NetadrToSockadr{ 0xCE6B90 };
|
||||||
|
WEAK symbol<void(netsrc_t, netadr_s*, const char*)> NET_OutOfBandPrint{ 0xBB4EE0 };
|
||||||
|
WEAK symbol<void(netsrc_t sock, int length, const void* data, const netadr_s* to)> NET_SendLoopPacket{ 0xBB50A0 };
|
||||||
|
WEAK symbol<bool(const char* s, netadr_s* a)> NET_StringToAdr{ 0xBB5180 };
|
||||||
|
WEAK symbol<int(netadr_s a, netadr_s b)> NET_CompareAdr{ 0xBB49B0 };
|
||||||
|
WEAK symbol<int(netadr_s a, netadr_s b)> NET_CompareBaseAdr{ 0xBB4A00 };
|
||||||
|
|
||||||
WEAK symbol<GfxFont* (const char* font, int size)> R_RegisterFont{ 0xDFC670 };
|
WEAK symbol<GfxFont* (const char* font, int size)> R_RegisterFont{ 0xDFC670 };
|
||||||
WEAK symbol<int(const char* text, int maxChars, GfxFont* font)> R_TextWidth{ 0xDFC770 };
|
WEAK symbol<int(const char* text, int maxChars, GfxFont* font)> R_TextWidth{ 0xDFC770 };
|
||||||
WEAK symbol<int(void* font)> R_GetFontHeight{ 0x12727B0 };
|
WEAK symbol<int(void* font)> R_GetFontHeight{ 0x12727B0 };
|
||||||
@ -108,6 +120,8 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<HANDLE(Sys_Folder folder, const char* baseFilename)> Sys_CreateFile{ 0xCFDF50 };
|
WEAK symbol<HANDLE(Sys_Folder folder, const char* baseFilename)> Sys_CreateFile{ 0xCFDF50 };
|
||||||
|
|
||||||
|
WEAK symbol<void(int, void const*, const netadr_s*)> Sys_SendPacket{ 0xD57DE0 };
|
||||||
|
|
||||||
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x9E4090 };
|
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x9E4090 };
|
||||||
|
|
||||||
WEAK symbol<void(const char* string)> SV_Cmd_TokenizeString{ 0xB7DD00 };
|
WEAK symbol<void(const char* string)> SV_Cmd_TokenizeString{ 0xB7DD00 };
|
||||||
@ -149,4 +163,6 @@ namespace game
|
|||||||
WEAK symbol<int> sv_map_restart{ 0x6B2C9D4 };
|
WEAK symbol<int> sv_map_restart{ 0x6B2C9D4 };
|
||||||
WEAK symbol<int> sv_loadScripts{ 0x6B2C9D8 };
|
WEAK symbol<int> sv_loadScripts{ 0x6B2C9D8 };
|
||||||
WEAK symbol<int> sv_migrate{ 0x6B2C9DC };
|
WEAK symbol<int> sv_migrate{ 0x6B2C9DC };
|
||||||
|
|
||||||
|
WEAK symbol<SOCKET> query_socket{ 0x779FDC8 };
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user