mirror of
https://github.com/gwdevhub/gMod.git
synced 2026-07-15 15:09:30 +00:00
f07e180b53
* remove more unnecessary code * todo? * 1.5.5.0 * change GetHash from in_out parameter to return the hash * remove ForceReload bool for textures * remove textureserver, place logic in textureclient, not yet finished next up change FileToMod and shit to use modded_textures map * fix debug compilation errors * fix typo * should_update boolean, replace the entire MergeUpdate logic later * tidy up d3d9_dll.cpp and bits (#12) * define `ASSERT` Added minhook lib to tidy up hooks Remove cruft from dx9_dll.cpp * Bug fix * Another typo --------- Co-authored-by: Jon <> * gitignore * Proxy functions, cache dx9 device type * simplify LoadModsFromFile * move minhook dependency to fetch content * Make it work * Tweaked debug for file reads * Fixed inverse check * unordered_map * set should_update (yikes) * simplify libzippp.cmake * remove unnecessary code * rename project files (keep uMod_ prefix only for d3d9 classes) * remove unused Nothing() function * remove unnecessary fields * remove some code duplication refactor methods together * refactor SwitchTextures and UnswitchTextures together * move loaded_size into function * enable libzippp encryption again * copy data from opened zipentry and then delete the entry * fix hash bug in volume textures * const * change uMod_TextureClient to TextureClient * revert libzippp.cmake * 1.5.6
252 lines
8.9 KiB
C++
252 lines
8.9 KiB
C++
#pragma once
|
|
|
|
#include <map>
|
|
|
|
#include "FileLoader.h"
|
|
#include "uMod_IDirect3DTexture9.h"
|
|
|
|
extern unsigned int gl_ErrorState;
|
|
|
|
struct TextureFileStruct {
|
|
std::vector<char> data{};
|
|
HashType crc_hash = 0; // hash value
|
|
};
|
|
|
|
template <typename T>
|
|
concept uModTexturePtr = requires(T a)
|
|
{
|
|
std::same_as<uMod_IDirect3DTexture9*, T> ||
|
|
std::same_as<uMod_IDirect3DVolumeTexture9*, T> ||
|
|
std::same_as<uMod_IDirect3DCubeTexture9*, T>;
|
|
};
|
|
|
|
template <typename T>
|
|
concept uModTexturePtrPtr = uModTexturePtr<std::remove_pointer_t<T>>;
|
|
|
|
/*
|
|
* An object of this class is owned by each d3d9 device.
|
|
* functions called by the Server are called from the server thread instance.
|
|
* All other functions are called from the render thread instance of the game itself.
|
|
*/
|
|
class TextureClient {
|
|
public:
|
|
TextureClient(IDirect3DDevice9* device);
|
|
~TextureClient();
|
|
|
|
int AddTexture(uModTexturePtr auto pTexture);
|
|
int RemoveTexture(uModTexturePtr auto pTexture); //called from uMod_IDirect3DTexture9::Release()
|
|
int LookUpToMod(uModTexturePtr auto pTexture);
|
|
// called at the end AddTexture(...) and from Device->UpdateTexture(...)
|
|
|
|
int MergeUpdate(); //called from uMod_IDirect3DDevice9::BeginScene()
|
|
|
|
// Add TpfEntry data, return size of data added. 0 on failure.
|
|
unsigned long AddFile(TpfEntry& entry);
|
|
|
|
std::vector<uMod_IDirect3DTexture9*> OriginalTextures;
|
|
// stores the pointer to the uMod_IDirect3DTexture9 objects created by the game
|
|
std::vector<uMod_IDirect3DVolumeTexture9*> OriginalVolumeTextures;
|
|
// stores the pointer to the uMod_IDirect3DVolumeTexture9 objects created by the game
|
|
std::vector<uMod_IDirect3DCubeTexture9*> OriginalCubeTextures;
|
|
// stores the pointer to the uMod_IDirect3DCubeTexture9 objects created by the game
|
|
|
|
D3DCOLOR FontColour;
|
|
D3DCOLOR TextureColour;
|
|
|
|
void Initialize();
|
|
|
|
private:
|
|
IDirect3DDevice9* D3D9Device;
|
|
// Cached info about whether this id a dx9ex device or not; used for proxy functions
|
|
bool isDirectXExDevice = false;
|
|
|
|
// DX9 proxy functions
|
|
uMod_IDirect3DTexture9* GetSingleTexture();
|
|
uMod_IDirect3DVolumeTexture9* GetSingleVolumeTexture();
|
|
uMod_IDirect3DCubeTexture9* GetSingleCubeTexture();
|
|
int SetLastCreatedTexture(uMod_IDirect3DTexture9*);
|
|
int SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9*);
|
|
int SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9*);
|
|
|
|
bool should_update = false;
|
|
|
|
int LockMutex();
|
|
int UnlockMutex();
|
|
HANDLE Mutex;
|
|
|
|
std::unordered_map<HashType, TextureFileStruct*> modded_textures;
|
|
// array which stores the file in memory and the hash of each texture to be modded
|
|
|
|
// called if a target texture is found
|
|
int LoadTexture(TextureFileStruct* file_in_memory, uModTexturePtrPtr auto ppTexture);
|
|
|
|
void LoadModsFromFile(const char* source);
|
|
};
|
|
|
|
int TextureClient::AddTexture(uModTexturePtr auto pTexture)
|
|
{
|
|
if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DTexture9*>) {
|
|
SetLastCreatedTexture(nullptr);
|
|
}
|
|
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DVolumeTexture9*>) {
|
|
SetLastCreatedVolumeTexture(nullptr);
|
|
}
|
|
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DCubeTexture9*>) {
|
|
SetLastCreatedCubeTexture(nullptr);
|
|
}
|
|
|
|
if (pTexture->FAKE) {
|
|
return RETURN_OK; // this is a fake texture
|
|
}
|
|
|
|
if (gl_ErrorState & uMod_ERROR_FATAL) {
|
|
return RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
Message("TextureClient::AddTexture( Cube: %p): %p (thread: %u)\n", pTexture, this, GetCurrentThreadId());
|
|
|
|
pTexture->Hash = pTexture->GetHash();
|
|
if (!pTexture->Hash) {
|
|
return RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DTexture9*>) {
|
|
OriginalTextures.push_back(pTexture);
|
|
}
|
|
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DVolumeTexture9*>) {
|
|
OriginalVolumeTextures.push_back(pTexture);
|
|
}
|
|
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DCubeTexture9*>) {
|
|
OriginalCubeTextures.push_back(pTexture);
|
|
}
|
|
|
|
return LookUpToMod(pTexture); // check if this texture should be modded
|
|
}
|
|
|
|
int TextureClient::RemoveTexture(uModTexturePtr auto pTexture)
|
|
{
|
|
Message("TextureClient::RemoveTexture( %p, %#lX): %p\n", pTexture, pTexture->Hash, this);
|
|
|
|
if (gl_ErrorState & uMod_ERROR_FATAL) {
|
|
return RETURN_FATAL_ERROR;
|
|
}
|
|
|
|
if (!pTexture->FAKE) {
|
|
if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DTexture9*>) {
|
|
utils::erase_first(OriginalTextures, pTexture);
|
|
}
|
|
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DVolumeTexture9*>) {
|
|
utils::erase_first(OriginalVolumeTextures, pTexture);
|
|
}
|
|
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DCubeTexture9*>) {
|
|
utils::erase_first(OriginalCubeTextures, pTexture);
|
|
}
|
|
}
|
|
if (!pTexture->Reference)
|
|
return RETURN_OK; // Should this ever happen?
|
|
return RETURN_OK;
|
|
}
|
|
|
|
int TextureClient::LookUpToMod(uModTexturePtr auto pTexture)
|
|
{
|
|
Message("TextureClient::LookUpToMod( %p): hash: %#lX, %p\n", pTexture, pTexture->Hash, this);
|
|
int ret = RETURN_OK;
|
|
|
|
if (pTexture->CrossRef_D3Dtex != nullptr)
|
|
return ret; // bug, this texture is already switched
|
|
|
|
const auto found = modded_textures.find(pTexture->Hash);
|
|
if (found == modded_textures.end())
|
|
return ret;
|
|
|
|
const auto textureFileStruct = found->second;
|
|
|
|
decltype(pTexture) fake_Texture;
|
|
ret = LoadTexture(textureFileStruct, &fake_Texture);
|
|
if (ret != RETURN_OK)
|
|
return ret;
|
|
|
|
ret = SwitchTextures(fake_Texture, pTexture);
|
|
if (ret != RETURN_OK) {
|
|
Message("TextureClient::LookUpToMod(): textures not switched %#lX\n", textureFileStruct->crc_hash);
|
|
fake_Texture->Release();
|
|
return ret;
|
|
}
|
|
fake_Texture->Reference = textureFileStruct;
|
|
return ret;
|
|
}
|
|
|
|
int TextureClient::LoadTexture(TextureFileStruct* file_in_memory, uModTexturePtrPtr auto ppTexture)
|
|
{
|
|
Message("LoadTexture( %p, %p, %#lX): %p\n", file_in_memory, ppTexture, file_in_memory->crc_hash, this);
|
|
if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DTexture9**>) {
|
|
if (D3D_OK != D3DXCreateTextureFromFileInMemoryEx(
|
|
D3D9Device, file_in_memory->data.data(),
|
|
file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT,
|
|
D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
|
|
D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr,
|
|
(IDirect3DTexture9**)ppTexture)) {
|
|
*ppTexture = nullptr;
|
|
return RETURN_TEXTURE_NOT_LOADED;
|
|
}
|
|
SetLastCreatedTexture(nullptr);
|
|
}
|
|
else if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DVolumeTexture9**>) {
|
|
if (D3D_OK != D3DXCreateVolumeTextureFromFileInMemoryEx(
|
|
D3D9Device, file_in_memory->data.data(),
|
|
file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT,
|
|
D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
|
|
D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0,
|
|
nullptr,
|
|
nullptr,
|
|
(IDirect3DVolumeTexture9**)ppTexture)) {
|
|
*ppTexture = nullptr;
|
|
return RETURN_TEXTURE_NOT_LOADED;
|
|
}
|
|
SetLastCreatedVolumeTexture(nullptr);
|
|
}
|
|
else if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DCubeTexture9**>) {
|
|
if (D3D_OK != D3DXCreateCubeTextureFromFileInMemoryEx(
|
|
D3D9Device, file_in_memory->data.data(), file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, 0,
|
|
D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
|
|
D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr,
|
|
(IDirect3DCubeTexture9**)ppTexture)) {
|
|
*ppTexture = nullptr;
|
|
return RETURN_TEXTURE_NOT_LOADED;
|
|
}
|
|
SetLastCreatedCubeTexture(nullptr);
|
|
}
|
|
(*ppTexture)->FAKE = true;
|
|
|
|
Message("LoadTexture( %p, %#lX): DONE\n", *ppTexture, file_in_memory->crc_hash);
|
|
return RETURN_OK;
|
|
}
|
|
|
|
template<typename T> requires uModTexturePtr<T>
|
|
void UnswitchTextures(T pTexture)
|
|
{
|
|
decltype(pTexture) CrossRef = pTexture->CrossRef_D3Dtex;
|
|
if (CrossRef != nullptr) {
|
|
std::swap(pTexture->m_D3Dtex, CrossRef->m_D3Dtex);
|
|
|
|
// cancel the link
|
|
CrossRef->CrossRef_D3Dtex = nullptr;
|
|
pTexture->CrossRef_D3Dtex = nullptr;
|
|
}
|
|
}
|
|
|
|
template<typename T> requires uModTexturePtr<T>
|
|
inline int SwitchTextures(T pTexture1, T pTexture2)
|
|
{
|
|
if (pTexture1->m_D3Ddev == pTexture2->m_D3Ddev && pTexture1->CrossRef_D3Dtex == nullptr && pTexture2->CrossRef_D3Dtex == nullptr) {
|
|
// make cross reference
|
|
pTexture1->CrossRef_D3Dtex = pTexture2;
|
|
pTexture2->CrossRef_D3Dtex = pTexture1;
|
|
|
|
// switch textures
|
|
std::swap(pTexture1->m_D3Dtex, pTexture2->m_D3Dtex);
|
|
return RETURN_OK;
|
|
}
|
|
return RETURN_TEXTURE_NOT_SWITCHED;
|
|
}
|