From 2fcd18483399c51d56cec433664013f914424f87 Mon Sep 17 00:00:00 2001 From: Federico Cecchetto Date: Wed, 8 Jun 2022 00:39:48 +0200 Subject: [PATCH] Images component --- src/client/component/images.cpp | 123 ++++++++++++++++++++++++++ src/client/component/images.hpp | 6 ++ src/client/component/ui_scripting.cpp | 16 ++-- 3 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 src/client/component/images.cpp create mode 100644 src/client/component/images.hpp diff --git a/src/client/component/images.cpp b/src/client/component/images.cpp new file mode 100644 index 00000000..9004171d --- /dev/null +++ b/src/client/component/images.cpp @@ -0,0 +1,123 @@ +#include +#include "loader/component_loader.hpp" + +#include "images.hpp" +#include "console.hpp" +#include "filesystem.hpp" + +#include "game/game.hpp" + +#include +#include +#include +#include +#include + +namespace images +{ + namespace + { + utils::hook::detour load_texture_hook; + utils::hook::detour setup_texture_hook; + utils::concurrency::container> overriden_textures; + + std::optional load_image(game::GfxImage* image) + { + std::string data{}; + overriden_textures.access([&](const std::unordered_map& textures) + { + if (const auto i = textures.find(image->name); i != textures.end()) + { + data = i->second; + } + }); + + if (data.empty() && !filesystem::read_file(utils::string::va("images/%s.png", image->name), &data)) + { + return {}; + } + + return {std::move(data)}; + } + + std::optional load_raw_image_from_file(game::GfxImage* image) + { + const auto image_file = load_image(image); + if (!image_file) + { + return {}; + } + + return utils::image(*image_file); + } + + bool load_custom_texture(game::GfxImage* image) + { + auto raw_image = load_raw_image_from_file(image); + if (!raw_image) + { + return false; + } + + image->imageFormat = 0x1000003; + image->resourceSize = -1; + + D3D11_SUBRESOURCE_DATA data{}; + data.SysMemPitch = raw_image->get_width() * 4; + data.SysMemSlicePitch = data.SysMemPitch * raw_image->get_height(); + data.pSysMem = raw_image->get_buffer(); + + game::Image_Setup(image, raw_image->get_width(), raw_image->get_height(), image->depth, image->numElements, + image->imageFormat, DXGI_FORMAT_R8G8B8A8_UNORM, image->name, &data); + + return true; + } + + void load_texture_stub(game::GfxImage* image, void* a2, int* a3) + { + try + { + if (load_custom_texture(image)) + { + return; + } + } + catch (std::exception& e) + { + console::error("Failed to load image %s: %s\n", image->name, e.what()); + } + + load_texture_hook.invoke(image, a2, a3); + } + + int setup_texture_stub(game::GfxImage* image, void* a2, void* a3) + { + if (image->resourceSize == -1) + { + return 0; + } + + return setup_texture_hook.invoke(image, a2, a3); + } + } + + void override_texture(std::string name, std::string data) + { + overriden_textures.access([&](std::unordered_map& textures) + { + textures[std::move(name)] = std::move(data); + }); + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + setup_texture_hook.create(SELECT_VALUE(0x55F870_b, 0x6829C0_b), setup_texture_stub); + load_texture_hook.create(SELECT_VALUE(0x83300_b, 0xA4AA0_b), load_texture_stub); + } + }; +} + +REGISTER_COMPONENT(images::component) diff --git a/src/client/component/images.hpp b/src/client/component/images.hpp new file mode 100644 index 00000000..a1c81344 --- /dev/null +++ b/src/client/component/images.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace images +{ + void override_texture(std::string name, std::string data); +} diff --git a/src/client/component/ui_scripting.cpp b/src/client/component/ui_scripting.cpp index 8ee38cfa..0c03036f 100644 --- a/src/client/component/ui_scripting.cpp +++ b/src/client/component/ui_scripting.cpp @@ -192,15 +192,18 @@ namespace ui_scripting return fps::get_fps(); }; - game_type["getping"] = [](const game&) + if (::game::environment::is_mp()) { - if ((*::game::mp::client_state) == nullptr) + game_type["getping"] = [](const game&) { - return 0; - } + if ((*::game::mp::client_state) == nullptr) + { + return 0; + } - return (*::game::mp::client_state)->ping; - }; + return (*::game::mp::client_state)->ping; + }; + } game_type["issingleplayer"] = [](const game&) { @@ -537,7 +540,6 @@ namespace ui_scripting command::add("lui_restart", []() { - utils::hook::invoke(SELECT_VALUE(0xFB370_b, 0x2707C0_b)); utils::hook::invoke(SELECT_VALUE(0x1052C0_b, 0x27BEC0_b)); }); }