diff --git a/deps/libtomcrypt b/deps/libtomcrypt index f1118b46..1de3f2a1 160000 --- a/deps/libtomcrypt +++ b/deps/libtomcrypt @@ -1 +1 @@ -Subproject commit f1118b464773616c1f73862cc29baf99eeabe849 +Subproject commit 1de3f2a1f61833428f27ff606f8e9b6dc91ad803 diff --git a/deps/protobuf b/deps/protobuf index 1e86ef4e..e222997c 160000 --- a/deps/protobuf +++ b/deps/protobuf @@ -1 +1 @@ -Subproject commit 1e86ef4e9f0b9c9e8bd8d62a61e141f139366920 +Subproject commit e222997c5bb136b4f079d5fdb1c9852bfadb2b3a diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.cpp b/src/Components/Modules/AssetInterfaces/IMaterial.cpp index 39e95fc9..7e875f52 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterial.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterial.cpp @@ -307,7 +307,7 @@ namespace Assets { std::vector textureList; - for (auto texture : textures.array_items()) + for (auto& texture : textures.array_items()) { if (!texture.is_array()) continue; if (textureList.size() >= 0xFF) break; diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 00d43e76..cf0343b8 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -221,7 +221,7 @@ namespace Components return false; } - Utils::IO::CreateDir("usermaps/" + download->mod); + if (download->isMap) Utils::IO::CreateDir("usermaps/" + download->mod); Utils::IO::WriteFile(path, fDownload.buffer); return true; diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 4bf56fc7..3f140a01 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -442,11 +442,20 @@ namespace Components return 0; } - int Maps::TriggerReconnectForMap(const char* mapname) + void Maps::LoadNewMapCommand(char* buffer, size_t size, const char* /*format*/, const char* mapname, const char* gametype) + { + unsigned int hash = Maps::GetUsermapHash(mapname); + _snprintf_s(buffer, size, size, "loadingnewmap\n%s\n%s\n%d", mapname, gametype, hash); + } + + int Maps::TriggerReconnectForMap(Game::msg_t* msg, const char* mapname) { Theatre::StopRecording(); - if(!Maps::CheckMapInstalled(mapname, false, true)) + char hashBuf[100] = { 0 }; + unsigned int hash = atoi(Game::MSG_ReadStringLine(msg, hashBuf, sizeof hashBuf)); + + if(!Maps::CheckMapInstalled(mapname, false, true) || hash && hash != Maps::GetUsermapHash(mapname)) { // Reconnecting forces the client to download the new map Command::Execute("disconnect", false); @@ -468,8 +477,9 @@ namespace Components pushad push [esp + 28h] + push ebp call Maps::TriggerReconnectForMap - add esp, 4h + add esp, 8h mov[esp + 20h], eax @@ -973,7 +983,7 @@ namespace Components Utils::Hook(0x51B46A, Maps::LoadRawSun, HOOK_CALL).install()->quick(); // Disable distortion on custom maps - Utils::Hook(0x50AA47, Maps::SetDistortionStub, HOOK_CALL).install()->quick(); + //Utils::Hook(0x50AA47, Maps::SetDistortionStub, HOOK_CALL).install()->quick(); // Disable speculars on custom maps Utils::Hook(0x525EA6, Maps::SetSpecularStub1, HOOK_CALL).install()->quick(); @@ -1000,6 +1010,11 @@ namespace Components }, 6s); }); + if(Dedicated::IsEnabled()) + { + Utils::Hook(0x4A7251, Maps::LoadNewMapCommand, HOOK_CALL).install()->quick(); + } + // Download the map before a maprotation if necessary // Conflicts with Theater's SV map rotation check, but this one is safer! Utils::Hook(0x5AA91C, Maps::RotateCheckStub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Maps.hpp b/src/Components/Modules/Maps.hpp index c1ee8af4..1becaa63 100644 --- a/src/Components/Modules/Maps.hpp +++ b/src/Components/Modules/Maps.hpp @@ -112,8 +112,9 @@ namespace Components static void SpawnServerStub(); static void LoadMapLoadscreenStub(); - static int TriggerReconnectForMap(const char* mapname); + static int TriggerReconnectForMap(Game::msg_t* msg, const char* mapname); static void RotateCheckStub(); + static void LoadNewMapCommand(char* buffer, size_t size, const char* format, const char* mapname, const char* gametype); static const char* LoadArenaFileStub(const char* name, char* buffer, int size); diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index c6527f99..7c192e91 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -14,7 +14,7 @@ namespace Components if (nodes.empty()) return; auto nodeList = Utils::String::Explode(nodes, '\n'); - for (auto node : nodeList) + for (auto& node : nodeList) { Utils::String::Replace(node, "\r", ""); node = Utils::String::Trim(node); @@ -71,7 +71,7 @@ namespace Components //list.set_is_dedi(Dedicated::IsDedicated()); std::lock_guard _(Node::NodeMutex); - for (auto node : Node::Nodes) + for (auto& node : Node::Nodes) { if (node.state == Node::STATE_VALID && node.registered) { @@ -114,7 +114,7 @@ namespace Components unsigned int count = 0; std::lock_guard _(Node::NodeMutex); - for (auto node : Node::Nodes) + for (auto& node : Node::Nodes) { if (node.state == Node::STATE_VALID) { @@ -416,7 +416,7 @@ namespace Components packet.set_signature(Utils::Cryptography::ECC::SignMessage(Node::SignatureKey, challenge)); std::lock_guard _(Node::NodeMutex); - for (auto node : Node::Nodes) + for (auto& node : Node::Nodes) { Network::SendCommand(node.address, "nodeDeregister", packet.SerializeAsString()); } @@ -846,7 +846,7 @@ namespace Components Logger::Print("Nodes: %d (%d)\n", Node::Nodes.size(), Node::GetValidNodeCount()); std::lock_guard _(Node::NodeMutex); - for (auto node : Node::Nodes) + for (auto& node : Node::Nodes) { Logger::Print("%s\t(%s)\n", node.address.getCString(), Node::GetStateName(node.state)); } @@ -872,7 +872,17 @@ namespace Components { Logger::Print("Resynchronizing nodes...\n"); - Node::LoadNodeRemotePreset(); + static bool threadRunning = false; + + if (!threadRunning) + { + threadRunning = true; + std::thread([]() + { + Node::LoadNodeRemotePreset(); + threadRunning = false; + }).detach(); + } std::lock_guard _(Node::NodeMutex); for (auto& node : Node::Nodes) @@ -894,6 +904,33 @@ namespace Components Node::LoadNodeRemotePreset(); }).detach(); }); + + if (Dedicated::IsEnabled()) + { + Network::Handle("getServersRequest", [](Network::Address target, std::string) + { + std::string data; + + { + std::lock_guard _(Node::NodeMutex); + for (auto& node : Node::Nodes) + { + if (node.state == Node::STATE_VALID && node.isDedi) + { + Game::netIP_t ip = node.address.getIP(); + unsigned short port = htons(node.address.getPort()); + data.append(reinterpret_cast(&ip.full), 4); + data.append(reinterpret_cast(&port), 2); + data.append("\\"); + } + } + + data.append("EOT"); + } + + Network::SendCommand(target, "getServersResponse", data); + }); + } } Node::~Node() diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 69262661..a3168e47 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -184,7 +184,7 @@ namespace Components ServerList::RefreshContainer.sendCount = 0; ServerList::RefreshContainer.sentCount = 0; - for (auto server : tempList) + for (auto& server : tempList) { ServerList::InsertRequest(server.addr); } @@ -255,11 +255,13 @@ namespace Components if (list) list->clear(); ServerList::VisibleList.clear(); - ServerList::RefreshContainer.mutex.lock(); - ServerList::RefreshContainer.servers.clear(); - ServerList::RefreshContainer.sendCount = 0; - ServerList::RefreshContainer.sentCount = 0; - ServerList::RefreshContainer.mutex.unlock(); + + { + std::lock_guard _(ServerList::RefreshContainer.mutex); + ServerList::RefreshContainer.servers.clear(); + ServerList::RefreshContainer.sendCount = 0; + ServerList::RefreshContainer.sentCount = 0; + } if (ServerList::IsOfflineList()) { @@ -417,7 +419,7 @@ namespace Components auto list = ServerList::GetList(); if (list) { - for (auto server : *list) + for (auto& server : *list) { if (server.addr == container.target) { @@ -604,8 +606,7 @@ namespace Components void ServerList::Frame() { - // This is bad practice and might even cause undefined behaviour! - if (!ServerList::RefreshContainer.mutex.try_lock()) return; + std::lock_guard _(ServerList::RefreshContainer.mutex); if (ServerList::RefreshContainer.awatingList) { @@ -644,8 +645,6 @@ namespace Components } ServerList::UpdateVisibleInfo(); - - ServerList::RefreshContainer.mutex.unlock(); } void ServerList::UpdateSource() @@ -865,9 +864,10 @@ namespace Components ServerList::FavouriteList.clear(); ServerList::VisibleList.clear(); - ServerList::RefreshContainer.mutex.lock(); - ServerList::RefreshContainer.awatingList = false; - ServerList::RefreshContainer.servers.clear(); - ServerList::RefreshContainer.mutex.unlock(); + { + std::lock_guard _(ServerList::RefreshContainer.mutex); + ServerList::RefreshContainer.awatingList = false; + ServerList::RefreshContainer.servers.clear(); + } } } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 948e5822..2e205576 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -157,6 +157,7 @@ namespace Game MSG_ReadShort_t MSG_ReadShort = MSG_ReadShort_t(0x40BDD0); MSG_ReadInt64_t MSG_ReadInt64 = MSG_ReadInt64_t(0x4F1850); MSG_ReadString_t MSG_ReadString = MSG_ReadString_t(0x60E2B0); + MSG_ReadStringLine_t MSG_ReadStringLine = MSG_ReadStringLine_t(0x4FEF30); MSG_WriteByte_t MSG_WriteByte = MSG_WriteByte_t(0x48C520); MSG_WriteData_t MSG_WriteData = MSG_WriteData_t(0x4F4120); MSG_WriteLong_t MSG_WriteLong = MSG_WriteLong_t(0x41CA20); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 669aea85..68471344 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -397,6 +397,9 @@ namespace Game typedef char* (__cdecl * MSG_ReadString_t)(msg_t* msg); extern MSG_ReadString_t MSG_ReadString; + typedef char* (__cdecl * MSG_ReadStringLine_t)(msg_t *msg, char *string, unsigned int maxChars); + extern MSG_ReadStringLine_t MSG_ReadStringLine; + typedef int(__cdecl * MSG_ReadByte_t)(msg_t* msg); extern MSG_ReadByte_t MSG_ReadByte; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index fa8f20b9..00de300a 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -3945,19 +3945,22 @@ namespace Game }; #pragma pack(pop) - // Probably incomplete or wrong! #pragma pack(push, 4) struct usercmd_s { int serverTime; int buttons; - char weapon; - char offHandIndex; int angles[3]; + unsigned __int16 weapon; + unsigned __int16 primaryWeaponForAltMode; + unsigned __int16 offHandIndex; char forwardmove; char rightmove; float meleeChargeYaw; char meleeChargeDist; + char selectedLoc[2]; + char selectedLocAngle; + char remoteControlAngles[2]; }; #pragma pack(pop) diff --git a/src/Main.cpp b/src/Main.cpp index ec3a2bc8..09e0fb2c 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -2,8 +2,6 @@ namespace Main { - Utils::Hook EntryPointHook; - void SetEnvironment() { wchar_t exeName[512]; @@ -17,8 +15,6 @@ namespace Main void Initialize() { - Main::EntryPointHook.uninstall(); - Main::SetEnvironment(); Utils::Cryptography::Initialize(); Components::Loader::Initialize(); @@ -44,6 +40,20 @@ namespace Main Utils::Cache::Uninitialize(); google::protobuf::ShutdownProtobufLibrary(); } + + __declspec(naked) void EntryPoint() + { + __asm + { + pushad + call Main::Initialize + popad + + push 6BAC14h // Continue init routine + push 6CA062h // ___security_init_cookie + retn + } + } } BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) @@ -56,10 +66,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*l Steam::Proxy::RunMod(); // Ensure we're working with our desired binary - if (Utils::Hook::Get(0x4C0FFF) != 0x6824748B) - { - return FALSE; - } + if (Utils::Hook::Get(0x4C0FFF) != 0x6824748B) return FALSE; #ifndef DISABLE_ANTICHEAT []() @@ -73,21 +80,8 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*l //VirtualProtect(module, 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect); // Unprotect the entire process VirtualProtect(module + 0x1000, 0x2D6000, PAGE_EXECUTE_READ, &oldProtect); // Protect the .text segment - Main::EntryPointHook.initialize(0x6BAC0F, [] () - { - __asm - { - pushad - - // This has to be called, otherwise the hook is not uninstalled and we're looping into infinity - call Main::Initialize - - popad - - push 6BAC0Fh - retn - } - })->install(); + // Install entry point hook + Utils::Hook(0x6BAC0F, Main::EntryPoint, HOOK_JUMP).install()->quick(); } else if (ul_reason_for_call == DLL_PROCESS_DETACH) { diff --git a/src/Utils/CSV.cpp b/src/Utils/CSV.cpp index b69440ac..31d4282e 100644 --- a/src/Utils/CSV.cpp +++ b/src/Utils/CSV.cpp @@ -10,16 +10,6 @@ namespace Utils CSV::~CSV() { - for (auto row : this->dataMap) - { - for (auto entry : row) - { - entry.clear(); - } - - row.clear(); - } - this->dataMap.clear(); } @@ -84,7 +74,7 @@ namespace Utils { auto rows = Utils::String::Explode(buffer, '\n'); - for (auto row : rows) + for (auto& row : rows) { this->parseRow(row, allowComments); } diff --git a/src/Utils/Memory.hpp b/src/Utils/Memory.hpp index 0fb8e148..7d7efe8e 100644 --- a/src/Utils/Memory.hpp +++ b/src/Utils/Memory.hpp @@ -34,7 +34,7 @@ namespace Utils this->refMemory.clear(); - for (auto data : this->pool) + for (auto& data : this->pool) { Memory::Free(data); } diff --git a/src/Utils/Utils.hpp b/src/Utils/Utils.hpp index 050158ae..6c0bcbe4 100644 --- a/src/Utils/Utils.hpp +++ b/src/Utils/Utils.hpp @@ -92,7 +92,7 @@ namespace Utils std::vector> copiedSlots; Utils::Merge(&copiedSlots, this->slots); - for (auto slot : copiedSlots) + for (auto& slot : copiedSlots) { if (slot) { diff --git a/src/Utils/WebIO.cpp b/src/Utils/WebIO.cpp index b1aee4b1..3b928d34 100644 --- a/src/Utils/WebIO.cpp +++ b/src/Utils/WebIO.cpp @@ -435,7 +435,7 @@ namespace Utils for (auto file : list) this->deleteFile(file); this->listDirectories(".", list); - for (auto dir : list) this->deleteDirectory(dir); + for (auto& dir : list) this->deleteDirectory(dir); this->setDirectory(tempDir);