[Dedicated] Fix

This commit is contained in:
Diavolo 2022-06-16 16:15:26 +02:00
parent 144ba7efd3
commit 52c9602473
No known key found for this signature in database
GPG Key ID: FA77F074E98D98A5
21 changed files with 264 additions and 235 deletions

View File

@ -115,6 +115,9 @@ namespace Components
Loader::Register(new Events());
Loader::Pregame = false;
// Make sure preDestroy is called when the game shuts down
Scheduler::OnGameShutdown(Loader::PreDestroy);
}
void Loader::Uninitialize()

View File

@ -7,6 +7,12 @@ namespace Components
Dvar::Var Branding::CGDrawVersionY;
Game::dvar_t** Branding::Version = reinterpret_cast<Game::dvar_t**>(0x1AD7930);
#ifdef _DEBUG
constexpr auto* BUILD_TYPE = "IW4x_DEV MP";
#else
constexpr auto* BUILD_TYPE = "IW4x MP";
#endif
void Branding::CG_DrawVersion()
{
// Default values
@ -45,15 +51,9 @@ namespace Components
const char* Branding::GetVersionString()
{
#ifdef _DEBUG
const auto* buildType = "IW4x_DEV MP";
#else
const auto* buildType = "IW4x MP";
#endif
// IW4x is technically a beta
const auto* result = Utils::String::VA("%s %s build %s %s",
buildType, "(Beta)", Branding::GetBuildNumber(), reinterpret_cast<const char*>(0x7170A0));
BUILD_TYPE, "(Beta)", Branding::GetBuildNumber(), reinterpret_cast<const char*>(0x7170A0));
return result;
}
@ -103,6 +103,11 @@ namespace Components
// Short version dvar
Utils::Hook::Set<const char*>(0x60BD91, SHORTVERSION);
// Com_Init_Try_Block_Function
Utils::Hook::Set<const char*>(0x60BAF4, BUILD_TYPE);
Utils::Hook::Set<const char*>(0x60BAEf, SHORTVERSION);
Utils::Hook::Set<const char*>(0x60BAE5, __DATE__);
Utils::Hook(0x4B12B0, Branding::GetBuildNumber, HOOK_JUMP).install()->quick();
// Version string color

View File

@ -410,7 +410,7 @@ namespace Components
{
cg_chatWidth = Dvar::Register<int>("cg_chatWidth", 52, 1, std::numeric_limits<int>::max(), Game::DVAR_ARCHIVE, "The normalized maximum width of a chat message");
sv_disableChat = Dvar::Register<bool>("sv_disableChat", false, Game::dvar_flag::DVAR_NONE, "Disable chat messages from clients");
Scheduler::Once(Chat::AddChatCommands, Scheduler::Pipeline::MAIN);
Scheduler::OnGameInitialized(AddChatCommands, Scheduler::Pipeline::SERVER);
// Intercept chat sending
Utils::Hook(0x4D000B, PreSayStub, HOOK_CALL).install()->quick();

View File

@ -84,7 +84,7 @@ namespace Components
{
if (Loader::IsPregame())
{
MessageBoxA(nullptr, "Registering server commands in pregamestate is illegal!", nullptr, MB_ICONERROR);
MessageBoxA(nullptr, "Registering server commands in pregame state is illegal!", nullptr, MB_ICONERROR);
#ifdef DEBUG
__debugbreak();
@ -103,7 +103,7 @@ namespace Components
Command::AddRaw(name, Game::Cbuf_AddServerText);
}
FunctionMapSV.insert_or_assign(command, std::move(callback));
FunctionMapSV.insert_or_assign(command, callback);
}
void Command::AddRaw(const char* name, void(*callback)(), bool key)

View File

@ -53,9 +53,8 @@ namespace Components
static void Add(const char* name, const std::function<void()>& callback);
static void Add(const char* name, const std::function<void(Command::Params*)>& callback);
static void AddSV(const char* name, const std::function<void(Command::Params*)>& callback);
static void AddRaw(const char* name, void(*callback)(), bool key = false);
static void AddRawSV(const char* name, void(*callback)());
static void AddSV(const char* name, const std::function<void(Command::Params*)>& callback);
static void Execute(std::string command, bool sync = true);
static Game::cmd_function_t* Find(const std::string& command);
@ -64,6 +63,8 @@ namespace Components
static std::unordered_map<std::string, std::function<void(Command::Params*)>> FunctionMap;
static std::unordered_map<std::string, std::function<void(Command::Params*)>> FunctionMapSV;
static void AddRawSV(const char* name, void(*callback)());
static void MainCallback();
static void MainCallbackSV();
};

View File

@ -232,7 +232,7 @@ namespace Components
// Only skip intro here, invocation will be done later.
Utils::Hook::Set<BYTE>(0x60BECF, 0xEB);
Scheduler::Once([]()
Scheduler::Once([]
{
Command::Execute("openmenu popup_reconnectingtoparty", false);
}, Scheduler::Pipeline::CLIENT, 8s);

View File

@ -140,9 +140,6 @@ namespace Components
void Dedicated::AddDedicatedCommands()
{
Dvar::Register<const char*>("sv_sayName", "^7Console", Game::dvar_flag::DVAR_NONE, "The name to pose as for 'say' commands");
Dvar::Register<const char*>("sv_motd", "", Game::dvar_flag::DVAR_NONE, "A custom message of the day for servers");
// Say command
Command::AddSV("say", [](Command::Params* params)
{
@ -214,7 +211,7 @@ namespace Components
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled())
{
// Make sure all callbacks are handled
Scheduler::Loop(Steam::SteamAPI_RunCallbacks, Scheduler::Pipeline::MAIN);
Scheduler::Loop(Steam::SteamAPI_RunCallbacks, Scheduler::Pipeline::SERVER);
Dedicated::SVLanOnly = Dvar::Register<bool>("sv_lanOnly", false,
Game::dvar_flag::DVAR_NONE, "Don't act as node");
@ -282,7 +279,13 @@ namespace Components
if (!ZoneBuilder::IsEnabled())
{
Scheduler::Once(Dedicated::AddDedicatedCommands, Scheduler::Pipeline::MAIN);
Scheduler::Once([]
{
Dvar::Register<const char*>("sv_sayName", "^7Console", Game::dvar_flag::DVAR_NONE, "The name to pose as for 'say' commands");
Dvar::Register<const char*>("sv_motd", "", Game::dvar_flag::DVAR_NONE, "A custom message of the day for servers");
}, Scheduler::Pipeline::MAIN);
Scheduler::OnGameInitialized(Dedicated::AddDedicatedCommands, Scheduler::Pipeline::SERVER);
// Post initialization point
Utils::Hook(0x60BFBF, Dedicated::PostInitializationStub, HOOK_JUMP).install()->quick();
@ -295,13 +298,8 @@ namespace Components
}, Scheduler::Pipeline::SERVER, 10s);
// Heartbeats
Scheduler::Loop([]
{
if (Dvar::Var("sv_maxclients").get<int>() > 0)
{
Dedicated::Heartbeat();
}
}, Scheduler::Pipeline::SERVER, 2min);
Scheduler::Once(Dedicated::Heartbeat, Scheduler::Pipeline::SERVER);
Scheduler::Loop(Dedicated::Heartbeat, Scheduler::Pipeline::SERVER, 2min);
}
}
else

View File

@ -961,7 +961,7 @@ namespace Components
}, Scheduler::Pipeline::MAIN);
Events::OnVMShutdown([]()
Events::OnVMShutdown([]
{
Download::ScriptDownloads.clear();
});

View File

@ -213,6 +213,8 @@ namespace Components
Game::dvar_t* Dvar::Dvar_RegisterName(const char* name, const char* /*default*/, unsigned __int16 flags, const char* description)
{
// Name watcher
if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled())
{
Scheduler::Loop([]
{
static std::string lastValidName = "Unknown Soldier";
@ -232,7 +234,8 @@ namespace Components
lastValidName = name;
Friends::UpdateName();
}
}, Scheduler::MAIN, 3s); // Don't need to do this every frame
}, Scheduler::CLIENT, 3s); // Don't need to do this every frame
}
std::string username = "Unknown Soldier";

View File

@ -569,7 +569,9 @@ namespace Components
FastFiles::AddZonePath("zone\\patch\\");
FastFiles::AddZonePath("zone\\dlc\\");
Scheduler::Loop([]()
if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled())
{
Scheduler::Loop([]
{
if (FastFiles::Current().empty() || !Dvar::Var("ui_zoneDebug").get<bool>()) return;
@ -589,8 +591,9 @@ namespace Components
fastfileLoadProgress = 0.0f;
}
Game::R_AddCmdDrawText(Utils::String::VA("Loading FastFile: %s [%0.1f%%]", FastFiles::Current().data(), fastfileLoadProgress), 0x7FFFFFFF, font, 5.0f, static_cast<float>(Renderer::Height() - 5), 1.0f, 1.0f, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL);
Game::R_AddCmdDrawText(Utils::String::VA("Loading FastFile: %s [%0.1f%%]", FastFiles::Current().data(), fastfileLoadProgress), std::numeric_limits<int>::max(), font, 5.0f, static_cast<float>(Renderer::Height() - 5), 1.0f, 1.0f, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL);
}, Scheduler::Pipeline::RENDERER);
}
Command::Add("loadzone", [](Command::Params* params)
{

View File

@ -724,7 +724,7 @@ namespace Components
Friends::UpdateState();
Friends::UpdateFriends();
}, Scheduler::Pipeline::MAIN);
}, Scheduler::Pipeline::CLIENT);
}
Friends::~Friends()

View File

@ -246,24 +246,7 @@ namespace Components
}
}
Logger::Logger()
{
Dvar::Register<bool>("iw4x_onelog", false, Game::dvar_flag::DVAR_LATCH | Game::dvar_flag::DVAR_ARCHIVE, "Only write the game log to the 'userraw' OS folder");
Utils::Hook(0x642139, Logger::BuildOSPathStub, HOOK_JUMP).install()->quick();
Logger::PipeOutput(nullptr);
Scheduler::Loop(Logger::Frame, Scheduler::Pipeline::MAIN);
Utils::Hook(0x4B0218, Logger::GameLogStub, HOOK_CALL).install()->quick();
Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessageStub, HOOK_JUMP).install()->quick();
if (Loader::IsPerformingUnitTests())
{
Utils::Hook(Game::Com_Printf, Logger::PrintStub, HOOK_JUMP).install()->quick();
}
Scheduler::Once([]
void Logger::AddServerCommands()
{
Command::AddSV("log_add", [](Command::Params* params)
{
@ -285,22 +268,22 @@ namespace Components
if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast<unsigned int>(num) < Logger::LoggingAddresses[0].size())
{
auto addr = Logger::LoggingAddresses[0].begin() + num;
Logger::Print("Address %s removed\n", addr->getCString());
Logger::Print("Address {} removed\n", addr->getCString());
Logger::LoggingAddresses[0].erase(addr);
}
else
{
Network::Address addr(params->get(1));
auto i = std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr);
const auto i = std::find(Logger::LoggingAddresses[0].begin(), Logger::LoggingAddresses[0].end(), addr);
if (i != Logger::LoggingAddresses[0].end())
{
Logger::LoggingAddresses[0].erase(i);
Logger::Print("Address %s removed\n", addr.getCString());
Logger::Print("Address {} removed\n", addr.getCString());
}
else
{
Logger::Print("Address %s not found!\n", addr.getCString());
Logger::Print("Address {} not found!\n", addr.getCString());
}
}
});
@ -312,7 +295,7 @@ namespace Components
for (unsigned int i = 0; i < Logger::LoggingAddresses[0].size(); ++i)
{
Logger::Print("#%03d: %5s\n", i, Logger::LoggingAddresses[0][i].getCString());
Logger::Print("{}: {}\n", i, Logger::LoggingAddresses[0][i].getCString());
}
});
@ -320,7 +303,7 @@ namespace Components
{
if (params->size() < 2) return;
Network::Address addr(params->get(1));
const Network::Address addr(params->get(1));
if (std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr) == Logger::LoggingAddresses[1].end())
{
@ -335,23 +318,23 @@ namespace Components
int num = atoi(params->get(1));
if (Utils::String::VA("%i", num) == std::string(params->get(1)) && static_cast<unsigned int>(num) < Logger::LoggingAddresses[1].size())
{
auto addr = Logger::LoggingAddresses[1].begin() + num;
Logger::Print("Address %s removed\n", addr->getCString());
const auto addr = Logger::LoggingAddresses[1].begin() + num;
Logger::Print("Address {} removed\n", addr->getCString());
Logger::LoggingAddresses[1].erase(addr);
}
else
{
Network::Address addr(params->get(1));
const Network::Address addr(params->get(1));
auto i = std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr);
const auto i = std::find(Logger::LoggingAddresses[1].begin(), Logger::LoggingAddresses[1].end(), addr);
if (i != Logger::LoggingAddresses[1].end())
{
Logger::LoggingAddresses[1].erase(i);
Logger::Print("Address %s removed\n", addr.getCString());
Logger::Print("Address {} removed\n", addr.getCString());
}
else
{
Logger::Print("Address %s not found!\n", addr.getCString());
Logger::Print("Address {} not found!\n", addr.getCString());
}
}
});
@ -361,12 +344,31 @@ namespace Components
Logger::Print("# ID: Address\n");
Logger::Print("-------------\n");
for (unsigned int i = 0; i < Logger::LoggingAddresses[1].size(); ++i)
for (std::size_t i = 0; i < Logger::LoggingAddresses[1].size(); ++i)
{
Logger::Print("#%03d: %5s\n", i, Logger::LoggingAddresses[1][i].getCString());
Logger::Print("{}: {}\n", i, Logger::LoggingAddresses[1][i].getCString());
}
});
}, Scheduler::Pipeline::MAIN);
}
Logger::Logger()
{
Dvar::Register<bool>("iw4x_onelog", false, Game::dvar_flag::DVAR_LATCH | Game::dvar_flag::DVAR_ARCHIVE, "Only write the game log to the 'userraw' OS folder");
Utils::Hook(0x642139, Logger::BuildOSPathStub, HOOK_JUMP).install()->quick();
Logger::PipeOutput(nullptr);
Scheduler::Loop(Logger::Frame, Scheduler::Pipeline::SERVER);
Utils::Hook(0x4B0218, Logger::GameLogStub, HOOK_CALL).install()->quick();
Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessageStub, HOOK_JUMP).install()->quick();
if (Loader::IsPerformingUnitTests())
{
Utils::Hook(Game::Com_Printf, Logger::PrintStub, HOOK_JUMP).install()->quick();
}
Scheduler::OnGameInitialized(Logger::AddServerCommands, Scheduler::Pipeline::SERVER);
}
Logger::~Logger()

View File

@ -23,99 +23,99 @@ namespace Components
static void WarningInternal(int channel, std::string_view fmt, std::format_args&& args);
static void DebugInternal(bool verbose, const std::source_location& srcLoc, std::string_view fmt, std::format_args&& args);
static inline void Print(std::string_view fmt)
__forceinline static void Print(std::string_view fmt)
{
PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(0));
}
static inline void Print(int channel, std::string_view fmt)
__forceinline static void Print(int channel, std::string_view fmt)
{
PrintInternal(channel, fmt, std::make_format_args(0));
}
template <typename... Args>
static inline void Print(std::string_view fmt, Args&&... args)
__forceinline static void Print(std::string_view fmt, Args&&... args)
{
PrintInternal(Game::CON_CHANNEL_DONT_FILTER, fmt, std::make_format_args(args...));
}
template <typename... Args>
static inline void Print(int channel, std::string_view fmt, Args&&... args)
__forceinline static void Print(int channel, std::string_view fmt, Args&&... args)
{
PrintInternal(channel, fmt, std::make_format_args(args...));
}
static inline void Error(Game::errorParm_t error, std::string_view fmt)
__forceinline static void Error(Game::errorParm_t error, std::string_view fmt)
{
ErrorInternal(error, fmt, std::make_format_args(0));
}
template <typename... Args>
static inline void Error(Game::errorParm_t error, std::string_view fmt, Args&&... args)
__forceinline static void Error(Game::errorParm_t error, std::string_view fmt, Args&&... args)
{
ErrorInternal(error, fmt, std::make_format_args(args...));
}
static inline void Warning(int channel, std::string_view fmt)
__forceinline static void Warning(int channel, std::string_view fmt)
{
WarningInternal(channel, fmt, std::make_format_args(0));
}
template <typename... Args>
static inline void Warning(int channel, std::string_view fmt, Args&&... args)
__forceinline static void Warning(int channel, std::string_view fmt, Args&&... args)
{
WarningInternal(channel, fmt, std::make_format_args(args...));
}
static inline void PrintError(int channel, std::string_view fmt)
__forceinline static void PrintError(int channel, std::string_view fmt)
{
PrintErrorInternal(channel, fmt, std::make_format_args(0));
}
template <typename... Args>
static inline void PrintError(int channel, std::string_view fmt, Args&&... args)
__forceinline static void PrintError(int channel, std::string_view fmt, Args&&... args)
{
PrintErrorInternal(channel, fmt, std::make_format_args(args...));
}
#ifdef _DEBUG
static inline void DebugInfo([[maybe_unused]] std::string_view fmt)
__forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt)
{
DebugInternal(true, std::source_location::current(), fmt, std::make_format_args(0));
}
template <typename... Args>
static inline void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
__forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
{
DebugInternal(true, std::source_location::current(), fmt, std::make_format_args(args...));
}
static inline void Debug([[maybe_unused]] std::string_view fmt)
__forceinline static void Debug([[maybe_unused]] std::string_view fmt)
{
DebugInternal(false, std::source_location::current(), fmt, std::make_format_args(0));
}
template <typename... Args>
static inline void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
__forceinline static void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
{
DebugInternal(false, std::source_location::current(), fmt, std::make_format_args(args...));
}
#else
static inline void DebugInfo([[maybe_unused]] std::string_view fmt)
__forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt)
{
}
template <typename... Args>
static inline void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
__forceinline static void DebugInfo([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
{
}
static inline void Debug([[maybe_unused]] std::string_view fmt)
__forceinline static void Debug([[maybe_unused]] std::string_view fmt)
{
}
template <typename... Args>
static inline void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
__forceinline static void Debug([[maybe_unused]] std::string_view fmt, [[maybe_unused]] Args&&... args)
{
}
#endif
@ -136,5 +136,7 @@ namespace Components
static void RedirectOSPath(const char* file, char* folder);
static void NetworkLog(const char* data, bool gLog);
static void AddServerCommands();
};
}

View File

@ -7,6 +7,8 @@ namespace Components
std::vector<std::pair<std::string, std::string>> Maps::DependencyList;
std::vector<std::string> Maps::CurrentDependencies;
Dvar::Var Maps::RListSModels;
bool Maps::SPMap;
std::vector<Maps::DLC> Maps::DlcPacks;
@ -775,7 +777,7 @@ namespace Components
Scheduler::Once([]
{
Dvar::Register<bool>("isDlcInstalled_All", false, Game::DVAR_EXTERNAL | Game::DVAR_WRITEPROTECTED, "");
Dvar::Register<bool>("r_listSModels", false, Game::DVAR_NONE, "Display a list of visible SModels");
Maps::RListSModels = Dvar::Register<bool>("r_listSModels", false, Game::DVAR_NONE, "Display a list of visible SModels");
Maps::AddDlc({ 1, "Stimulus Pack", {"mp_complex", "mp_compact", "mp_storm", "mp_overgrown", "mp_crash"} });
Maps::AddDlc({ 2, "Resurgence Pack", {"mp_abandon", "mp_vacant", "mp_trailerpark", "mp_strike", "mp_fuel2"} });
@ -882,7 +884,7 @@ namespace Components
Utils::Hook(0x5A9D51, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick();
Utils::Hook(0x5B34DD, Maps::LoadMapLoadscreenStub, HOOK_CALL).install()->quick();
Command::Add("delayReconnect", [](Command::Params*)
Command::Add("delayReconnect", []([[maybe_unused]] Command::Params* params)
{
Scheduler::Once([]
{
@ -913,10 +915,16 @@ namespace Components
// Allow hiding specific smodels
Utils::Hook(0x50E67C, Maps::HideModelStub, HOOK_CALL).install()->quick();
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled())
{
return;
}
// Client only
Scheduler::Loop([]
{
auto*& gameWorld = *reinterpret_cast<Game::GfxWorld**>(0x66DEE94);
if (!Game::CL_IsCgameInitialized() || !gameWorld || !Dvar::Var("r_listSModels").get<bool>()) return;
if (!Game::CL_IsCgameInitialized() || !gameWorld || !Maps::RListSModels.get<bool>()) return;
std::map<std::string, int> models;
for (unsigned int i = 0; i < gameWorld->dpvs.smodelCount; ++i)

View File

@ -83,6 +83,8 @@ namespace Components
static std::vector<std::pair<std::string, std::string>> DependencyList;
static std::vector<std::string> CurrentDependencies;
static Dvar::Var RListSModels;
static void GetBSPName(char* buffer, size_t size, const char* format, const char* mapname);
static void LoadAssetRestrict(Game::XAssetType type, Game::XAssetHeader asset, const std::string& name, bool* restrict);
static void LoadMapZones(Game::XZoneInfo *zoneInfo, unsigned int zoneCount, int sync);

View File

@ -146,7 +146,7 @@ namespace Components
if (!address.isValid()) return;
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
for (auto& session : Node::Nodes)
{
if (session.address == address) return;
@ -160,7 +160,7 @@ namespace Components
std::vector<Node::Entry> Node::GetNodes()
{
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
return Node::Nodes;
}
@ -197,7 +197,7 @@ namespace Components
if (!frameLimit.elapsed(std::chrono::milliseconds(interval))) return;
frameLimit.update();
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
Dvar::Var queryLimit("net_serverQueryLimit");
int sentRequests = 0;
@ -220,7 +220,7 @@ namespace Components
void Node::Synchronize()
{
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
for (auto& node : Node::Nodes)
{
//if (node.isValid()) // Comment out to simulate 'syncnodes' behaviour
@ -237,7 +237,7 @@ namespace Components
Logger::DebugInfo("Received response from {}\n", address.getCString());
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
for (int i = 0; i < list.nodes_size(); ++i)
{
@ -282,9 +282,9 @@ namespace Components
}
}
void Node::SendList(Network::Address address)
void Node::SendList(const Network::Address& address)
{
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
// need to keep the message size below 1404 bytes else recipient will just drop it
std::vector<std::string> nodeListReponseMessages;
@ -320,11 +320,13 @@ namespace Components
auto i = 0;
for (const auto& nodeListData : nodeListReponseMessages)
{
Scheduler::Once([&]
Scheduler::Once([=]
{
Logger::DebugInfo("Sending {} nodeListResponse length to {}\n", nodeListData.length(), address.getCString());
#ifdef DEBUG_NODE
Logger::Debug("Sending {} nodeListResponse length to {}\n", nodeListData.length(), address.getCString());
#endif
Session::Send(address, "nodeListResponse", nodeListData);
}, Scheduler::Pipeline::MAIN, NODE_SEND_RATE * i++);
}, Scheduler::Pipeline::SERVER, NODE_SEND_RATE * i++);
}
}
@ -344,16 +346,16 @@ namespace Components
Node::StoreNodes(false);
}, Scheduler::Pipeline::ASYNC);
Scheduler::Loop(Node::RunFrame, Scheduler::Pipeline::MAIN);
Scheduler::Loop(Node::RunFrame, Scheduler::Pipeline::SERVER);
Session::Handle("nodeListResponse", Node::HandleResponse);
Session::Handle("nodeListRequest", [](Network::Address address, const std::string&)
Session::Handle("nodeListRequest", [](const Network::Address& address, const std::string&)
{
Node::SendList(address);
});
// Load stored nodes
auto loadNodes = []()
auto loadNodes = []
{
Node::LoadNodePreset();
Node::LoadNodes();
@ -374,7 +376,7 @@ namespace Components
{
Logger::Print("Nodes: {}\n", Node::Nodes.size());
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
for (auto& node : Node::Nodes)
{
Logger::Print("{}\t({})\n", node.address.getCString(), node.isValid() ? "Valid" : "Invalid");
@ -390,7 +392,7 @@ namespace Components
Node::~Node()
{
std::lock_guard<std::recursive_mutex> _(Node::Mutex);
std::lock_guard _(Node::Mutex);
Node::StoreNodes(true);
Node::Nodes.clear();
}

View File

@ -51,7 +51,7 @@ namespace Components
static void HandleResponse(Network::Address address, const std::string& data);
static void SendList(Network::Address address);
static void SendList(const Network::Address& address);
static void LoadNodePreset();
static void LoadNodes();

View File

@ -286,6 +286,8 @@ namespace Components
Party::Connect(Party::Container.target);
});
if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled())
{
Scheduler::Loop([]
{
if (Party::Container.valid)
@ -307,6 +309,7 @@ namespace Components
}
}, Scheduler::Pipeline::CLIENT);
}
// Basic info handler
Network::OnPacket("getInfo", [](const Network::Address& address, [[maybe_unused]] const std::string& data)

View File

@ -263,9 +263,6 @@ namespace Components
Utils::Hook(0x4FA448, QuickPatch::Dvar_RegisterConMinicon, HOOK_CALL).install()->quick();
// Make sure preDestroy is called when the game shuts down
Scheduler::OnGameShutdown(Loader::PreDestroy);
// protocol version (workaround for hacks)
Utils::Hook::Set<int>(0x4FB501, PROTOCOL);

View File

@ -15,7 +15,7 @@ namespace Components
std::queue<std::pair<Network::Address, std::string>> Session::SignatureQueue;
void Session::Send(Network::Address target, const std::string& command, const std::string& data)
void Session::Send(const Network::Address& target, const std::string& command, const std::string& data)
{
#ifdef DISABLE_SESSION
class DelayedResend
@ -26,27 +26,27 @@ namespace Components
std::string data;
};
DelayedResend* delayData = new DelayedResend;
auto* delayData = new DelayedResend;
delayData->target = target;
delayData->command = command;
delayData->data = data;
Network::SendCommand(target, command, data);
Scheduler::Once([delayData]()
Scheduler::Once([delayData]
{
Network::SendCommand(delayData->target, delayData->command, delayData->data);
delete delayData;
}, Scheduler::Pipeline::MAIN, 500ms + std::chrono::milliseconds(rand() % 200));
}, Scheduler::Pipeline::SERVER, 500ms + std::chrono::milliseconds(std::rand() % 200));
#else
std::lock_guard<std::recursive_mutex> _(Session::Mutex);
std::lock_guard _(Session::Mutex);
auto queue = Session::PacketQueue.find(target);
if (queue == Session::PacketQueue.end())
{
Session::PacketQueue[target] = std::queue<std::shared_ptr<Session::Packet>>();
queue = Session::PacketQueue.find(target);
if (queue == Session::PacketQueue.end()) Logger::Error("Failed to enqueue session packet!\n");
if (queue == Session::PacketQueue.end()) Logger::Error(Game::ERR_FATAL, "Failed to enqueue session packet!\n");
}
std::shared_ptr<Session::Packet> packet = std::make_shared<Session::Packet>();
@ -63,14 +63,14 @@ namespace Components
#ifdef DISABLE_SESSION
Network::OnPacket(packet, callback);
#else
std::lock_guard<std::recursive_mutex> _(Session::Mutex);
std::lock_guard _(Session::Mutex);
Session::PacketHandlers[packet] = callback;
#endif
}
void Session::RunFrame()
{
std::lock_guard<std::recursive_mutex> _(Session::Mutex);
std::lock_guard _(Session::Mutex);
for (auto queue = Session::PacketQueue.begin(); queue != Session::PacketQueue.end();)
{
@ -155,7 +155,7 @@ namespace Components
Session::Frame frame;
frame.challenge = Utils::Cryptography::Rand::GenerateChallenge();
std::lock_guard<std::recursive_mutex> _(Session::Mutex);
std::lock_guard _(Session::Mutex);
Session::Sessions[address] = frame;
Network::SendCommand(address, "sessionAck", frame.challenge);
@ -163,13 +163,13 @@ namespace Components
Network::OnPacket("sessionAck", [](const Network::Address& address, [[maybe_unused]] const std::string& data)
{
std::lock_guard<std::recursive_mutex> _(Session::Mutex);
std::lock_guard _(Session::Mutex);
Session::SignatureQueue.push({ address, data });
});
Network::OnPacket("sessionFin", [](Network::Address& address, [[maybe_unused]] const std::string& data)
{
std::lock_guard<std::recursive_mutex> _(Session::Mutex);
std::lock_guard _(Session::Mutex);
auto frame = Session::Sessions.find(address);
if (frame == Session::Sessions.end()) return;
@ -195,7 +195,7 @@ namespace Components
Session::~Session()
{
std::lock_guard<std::recursive_mutex> _(Session::Mutex);
std::lock_guard _(Session::Mutex);
Session::PacketHandlers.clear();
Session::PacketQueue.clear();
Session::SignatureQueue = std::queue<std::pair<Network::Address, std::string>>();

View File

@ -34,7 +34,7 @@ namespace Components
bool unitTest() override;
void preDestroy() override;
static void Send(Network::Address target, const std::string& command, const std::string& data = "");
static void Send(const Network::Address& target, const std::string& command, const std::string& data = "");
static void Handle(const std::string& packet, const Network::NetworkCallback& callback);
private: