diff --git a/data/ui_scripts/server_browser/__init__.lua b/data/ui_scripts/server_browser/__init__.lua index 493795a4..49cd0fc8 100644 --- a/data/ui_scripts/server_browser/__init__.lua +++ b/data/ui_scripts/server_browser/__init__.lua @@ -42,7 +42,7 @@ DataSources.LobbyServer = { SetModelValue(serverModel, "modName", serverInfo.modName) SetModelValue(serverModel, "mapName", serverInfo.map) SetModelValue(serverModel, "desc", serverInfo.desc) - -- Changed the client count to be the actual player count + -- Change the client count to be the actual player count local clientCount = serverInfo.playerCount - serverInfo.botCount SetModelValue(serverModel, "clientCount", clientCount) SetModelValue(serverModel, "maxClients", serverInfo.maxPlayers) @@ -54,7 +54,7 @@ DataSources.LobbyServer = { SetModelValue(serverModel, "ranked", serverInfo.ranked) SetModelValue(serverModel, "hardcore", serverInfo.hardcore) SetModelValue(serverModel, "zombies", serverInfo.zombies) - -- Added the bot count + -- Add the bot count SetModelValue(serverModel, "botCount", serverInfo.botCount) return serverModel else diff --git a/deps/curl b/deps/curl index d8df0d6d..8e21b1a0 160000 --- a/deps/curl +++ b/deps/curl @@ -1 +1 @@ -Subproject commit d8df0d6db7441b6e14920a7e16a10e32bdc9c7ae +Subproject commit 8e21b1a05f3c0ee098dbcb6c3d84cb61f102a122 diff --git a/src/client/component/chat.cpp b/src/client/component/chat.cpp index 41b1b44a..01bb52f3 100644 --- a/src/client/component/chat.cpp +++ b/src/client/component/chat.cpp @@ -85,6 +85,12 @@ namespace chat a.cmp(dword_ptr(rax, 0x16AE0), 0x0); // game's code a.jmp(0x14029905B_g); } + + void cl_handle_chat(char* dest, size_t dest_size, const char* src) + { + game::I_strcpy(dest, dest_size, src); + printf("%s\n", dest); + } } const char* get_client_name(const uint64_t xuid) @@ -96,7 +102,7 @@ namespace chat if (xuid < 19 && !game::is_server()) { - char buffer[256]; + char buffer[256]{}; game::CL_GetClientName(0, static_cast(xuid - 1), buffer, sizeof(buffer), true); return utils::string::va("%s\n", buffer); @@ -167,6 +173,9 @@ namespace chat { // Ignore some check that suppresses the chat utils::hook::nop(0x141DEA9BD_g, 2); + + // Add chat history to the in-game console + utils::hook::call(0x141DEAA0F_g, cl_handle_chat); // I_strcpy } } }; diff --git a/src/client/component/getinfo.cpp b/src/client/component/getinfo.cpp index 95e3d10b..b40c902a 100644 --- a/src/client/component/getinfo.cpp +++ b/src/client/component/getinfo.cpp @@ -116,8 +116,9 @@ namespace getinfo info.set("sv_running", std::to_string(game::is_server_running())); info.set("dedicated", game::is_server() ? "1" : "0"); info.set("hc", std::to_string(game::Com_GametypeSettings_GetUInt("hardcoremode", false))); - info.set("modName", workshop::get_mod_resized_name(game::get_dvar_string("fs_game"))); - info.set("modId", workshop::get_mod_publisher_id(game::get_dvar_string("fs_game"))); + info.set("modName", workshop::get_mod_resized_name()); + info.set("modId", workshop::get_mod_publisher_id()); + info.set("rounds_played", std::to_string(*game::level_rounds_played)); info.set("shortversion", SHORTVERSION); network::send(target, "infoResponse", info.build(), '\n'); diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index d6dc8fa5..3573e345 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -79,7 +79,6 @@ namespace script { if (data.size() >= sizeof(GSC_MAGIC) && !std::memcmp(data.data(), &GSC_MAGIC, sizeof(GSC_MAGIC))) { - auto base_name = script_file.substr(0, script_file.size() - 4); print_loading_script(script_file); load_script(script_file, data); } diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index 46199570..174e7c6a 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -16,7 +16,7 @@ namespace server_list { namespace { - utils::hook::detour lua_serverinfo_to_table_hook; + utils::hook::detour lua_server_info_to_table_hook; struct state { @@ -80,14 +80,14 @@ namespace server_list callback(true, result); } - void lua_serverinfo_to_table_stub(game::hks::lua_State* state, game::ServerInfo serverInfo, int index) + void lua_server_info_to_table_stub(game::hks::lua_State* state, game::ServerInfo server_info, int index) { - lua_serverinfo_to_table_hook.invoke(state, serverInfo, index); + lua_server_info_to_table_hook.invoke(state, server_info, index); if (state) { - auto botCount = atoi(game::Info_ValueForKey(serverInfo.tags, "bots")); - game::Lua_SetTableInt("botCount", botCount, state); + const auto bot_count = atoi(game::Info_ValueForKey(server_info.tags, "bots")); + game::Lua_SetTableInt("botCount", bot_count, state); } } @@ -98,13 +98,14 @@ namespace server_list void write_favorite_servers() { - favorite_servers.access([&](std::unordered_set& servers) + favorite_servers.access([](const std::unordered_set& servers) { - std::string servers_buffer = ""; - for (auto itr : servers) + std::string servers_buffer{}; + for (const auto& itr : servers) { - servers_buffer.append(utils::string::va("%i.%i.%i.%i:%u\n", itr.ipv4.a, itr.ipv4.b, itr.ipv4.c, itr.ipv4.d, itr.port)); + servers_buffer.append(utils::string::va("%i.%i.%i.%i:%hu\n", itr.ipv4.a, itr.ipv4.b, itr.ipv4.c, itr.ipv4.d, itr.port)); } + utils::io::write_file(get_favorite_servers_file_path(), servers_buffer); }); } @@ -120,11 +121,12 @@ namespace server_list favorite_servers.access([&path](std::unordered_set& servers) { servers.clear(); - std::string filedata; - if (utils::io::read_file(path, &filedata)) + + std::string data; + if (utils::io::read_file(path, &data)) { - auto srv = utils::string::split(filedata, '\n'); - for (auto server_address : srv) + const auto srv = utils::string::split(data, '\n'); + for (const auto& server_address : srv) { auto server = network::address_from_string(server_address); servers.insert(server); @@ -197,7 +199,7 @@ namespace server_list { master_state.access([&](state& s) { - handle_server_list_response(target, data, s); + handle_server_list_response(target, data, s); }); }); @@ -222,7 +224,7 @@ namespace server_list }); }, scheduler::async, 200ms); - lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub); + lua_server_info_to_table_hook.create(0x141F1FD10_g, lua_server_info_to_table_stub); scheduler::once([] { diff --git a/src/client/component/workshop.cpp b/src/client/component/workshop.cpp index 0dc9b4c5..cd6fb8d1 100644 --- a/src/client/component/workshop.cpp +++ b/src/client/component/workshop.cpp @@ -170,32 +170,34 @@ namespace workshop } } - std::string get_mod_resized_name(const std::string& dir_name) + std::string get_mod_resized_name() { - if (dir_name == "usermaps" || dir_name.empty()) + const std::string loaded_mod_id = game::getPublisherIdFromLoadedMod(); + + if (loaded_mod_id == "usermaps" || loaded_mod_id.empty()) { - return dir_name; + return loaded_mod_id; } - std::string result = dir_name; + std::string mod_name = loaded_mod_id; for (unsigned int i = 0; i < *game::modsCount; ++i) { const auto& mod_data = game::modsPool[i]; - if (utils::string::ends_with(mod_data.contentPathToZoneFiles, dir_name)) + if (mod_data.publisherId == loaded_mod_id) { - result = mod_data.title; + mod_name = mod_data.title; break; } } - if (result.size() > 31) + if (mod_name.size() > 31) { - result.resize(31); + mod_name.resize(31); } - return result; + return mod_name; } std::string get_usermap_publisher_id(const std::string& zone_name) @@ -218,29 +220,22 @@ namespace workshop return {}; } - std::string get_mod_publisher_id(const std::string& dir_name) + std::string get_mod_publisher_id() { - if (dir_name == "usermaps" || dir_name.empty()) + const std::string loaded_mod_id = game::getPublisherIdFromLoadedMod(); + + if (loaded_mod_id == "usermaps" || loaded_mod_id.empty()) { - return dir_name; + return loaded_mod_id; } - for (unsigned int i = 0; i < *game::modsCount; ++i) + if (!utils::string::is_numeric(loaded_mod_id)) { - const auto& mod_data = game::modsPool[i]; - if (utils::string::ends_with(mod_data.contentPathToZoneFiles, dir_name)) - { - if (!utils::string::is_numeric(mod_data.publisherId)) - { - printf("[ Workshop ] WARNING: The publisherId is not numerical you might have set your mod folder incorrectly!\n%s\n", - mod_data.absolutePathZoneFiles); - } - - return mod_data.publisherId; - } + printf("[ Workshop ] WARNING: The publisherId: %s, is not numerical you might have set your mod folder incorrectly!\n", + loaded_mod_id.data()); } - return {}; + return loaded_mod_id; } bool check_valid_usermap_id(const std::string& mapname, const std::string& pub_id) @@ -274,6 +269,11 @@ namespace workshop void setup_same_mod_as_host(const std::string& usermap, const std::string& mod) { + if (game::getPublisherIdFromLoadedMod() == mod) + { + return; + } + if (!usermap.empty() || mod != "usermaps") { game::loadMod(0, mod.data(), true); diff --git a/src/client/component/workshop.hpp b/src/client/component/workshop.hpp index 394ebd0a..219d20a8 100644 --- a/src/client/component/workshop.hpp +++ b/src/client/component/workshop.hpp @@ -3,8 +3,8 @@ namespace workshop { std::string get_usermap_publisher_id(const std::string& folder_name); - std::string get_mod_publisher_id(const std::string& folder_name); - std::string get_mod_resized_name(const std::string& folder_name); + std::string get_mod_publisher_id(); + std::string get_mod_resized_name(); bool check_valid_usermap_id(const std::string& mapname, const std::string& pub_id); bool check_valid_mod_id(const std::string& pub_id); void setup_same_mod_as_host(const std::string& usermap, const std::string& mod); diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 1c6a22e0..c635953c 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -1,6 +1,6 @@ #pragma once -#define PROTOCOL 6 +#define PROTOCOL 7 #define SUB_PROTOCOL 1 #ifdef __cplusplus diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index f78016bd..a909c00d 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -114,6 +114,7 @@ namespace game WEAK symbol CopyString{0x1422AC220, 0x14056BD70}; WEAK symbol isModLoaded{0x1420D5020}; + WEAK symbol getPublisherIdFromLoadedMod{0x1420D7680, 0x1404E3230}; WEAK symbol loadMod{0x1420D6930}; WEAK symbol reloadUserContent{0x1420D66C0, 0x1404E25C0}; @@ -214,6 +215,9 @@ namespace game // Utils WEAK symbol I_CleanStr{0x1422E9050, 0x140580E80}; + WEAK symbol I_strcpy{ + 0x1422E9410, 0x1405811E0 + }; // Variables WEAK symbol cmd_functions{0x15689DF58, 0x14946F860}; @@ -222,6 +226,7 @@ namespace game WEAK symbol g_entities{0x0, 0x1471031B0}; WEAK symbol level_time{0x0, 0x1474FDC94}; + WEAK symbol level_rounds_played{0x14A55BDEC, 0x1475097BC}; WEAK symbol ip_socket{0x157E75818, 0x14A640988}; diff --git a/src/client/main.cpp b/src/client/main.cpp index 2601dc63..749bf1a8 100644 --- a/src/client/main.cpp +++ b/src/client/main.cpp @@ -292,6 +292,11 @@ namespace const auto is_server = utils::flags::has_flag("dedicated") || (!has_client && has_server); + if (!has_client && !has_server) + { + throw std::runtime_error("Can't find a valid BlackOps3.exe or BlackOps3_UnrankedDedicatedServer.exe. Make sure you put boiii.exe in your Black Ops 3 installation folder."); + } + if (!is_server) { trigger_high_performance_gpu_switch(); diff --git a/src/common/utils/cryptography.cpp b/src/common/utils/cryptography.cpp index 5c5c1a8f..625403fb 100644 --- a/src/common/utils/cryptography.cpp +++ b/src/common/utils/cryptography.cpp @@ -224,9 +224,7 @@ namespace utils::cryptography { this->free(); - if (ecc_import(cs(key.data()), ul(key.size()), - &this->key_storage_) != CRYPT_OK - ) + if (ecc_import(cs(key.data()), ul(key.size()), &this->key_storage_) != CRYPT_OK) { ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); } @@ -242,7 +240,7 @@ namespace utils::cryptography return {cs(buffer), length}; } - return ""; + return {}; } std::string ecc::key::get_openssl() const @@ -255,7 +253,17 @@ namespace utils::cryptography return {cs(buffer), length}; } - return ""; + return {}; + } + + void ecc::key::set_openssl(const std::string& key) + { + this->free(); + + if (ecc_import_openssl(cs(key.data()), ul(key.size()), &this->key_storage_) != CRYPT_OK) + { + ZeroMemory(&this->key_storage_, sizeof(this->key_storage_)); + } } void ecc::key::free() @@ -305,12 +313,14 @@ namespace utils::cryptography std::string ecc::sign_message(const key& key, const std::string& message) { - if (!key.is_valid()) return ""; + if (!key.is_valid()) return {}; uint8_t buffer[512]; unsigned long length = sizeof(buffer); - ecc_sign_hash(cs(message.data()), ul(message.size()), buffer, &length, prng_.get_state(), prng_.get_id(), + const auto hash = sha512::compute(message); + + ecc_sign_hash(cs(hash.data()), ul(hash.size()), buffer, &length, prng_.get_state(), prng_.get_id(), &key.get()); return std::string(cs(buffer), length); @@ -320,11 +330,13 @@ namespace utils::cryptography { if (!key.is_valid()) return false; + const auto hash = sha512::compute(message); + auto result = 0; return (ecc_verify_hash(cs(signature.data()), ul(signature.size()), - cs(message.data()), - ul(message.size()), &result, + cs(hash.data()), + ul(hash.size()), &result, &key.get()) == CRYPT_OK && result != 0); } @@ -396,7 +408,6 @@ namespace utils::cryptography rsa_free(&new_key); }); - std::string out_data{}; out_data.resize(std::max(ul(data.size() * 3), ul(0x100))); diff --git a/src/common/utils/cryptography.hpp b/src/common/utils/cryptography.hpp index 456a950b..a53c6704 100644 --- a/src/common/utils/cryptography.hpp +++ b/src/common/utils/cryptography.hpp @@ -32,6 +32,7 @@ namespace utils::cryptography std::string serialize(int type = PK_PRIVATE) const; std::string get_openssl() const; + void set_openssl(const std::string& key); void free();