Sorry, didn't notice this thread before.
The GameUI007 interface is only retrieved from the GameUI library in "valve/cl_dlls/GameUI.ext".
This is the engine code for it (reverse engineered):
char szDllName[ 512 ];
snprintf(szDllName, sizeof( szDllName ), "valve/cl_dlls/gameui.so");
COM_FixSlashes(szDllName);
FS_GetLocalCopy(szDllName);
this->m_hStaticGameUIModule = Sys_LoadModule(szDllName);
CreateInterfaceFn gameUIFactory = Sys_GetFactory(this->m_hStaticGameUIModule);
this->m_FactoryList[this->m_iNumFactories] = gameUIFactory;
if ( gameUIFactory )
{
staticGameUIFuncs = (IGameUI *)gameUIFactory ("GameUI007", nullptr);
staticGameConsole = (IGameConsole *)gameUIFactory ("GameConsole003", nullptr);
staticCareerUI = (ICareerUI *)gameUIFactory ("CareerUI001", nullptr);
++this->m_iNumFactories;
}
You cannot override GameUI because it will always load from valve/cl_dlls, and it will always load the interface from that library.
I've created a new issue requesting that GameUI be open sourced so it can be overridden by mod developers:
https://github.com/ValveSoftware/halflife/issues/1763I don't expect a response from anybody.
One thing you can try - and this is an epic hack - is to try to overwrite the vtable for the class so it redirects calls to your own implementation, and then pass them through to the original afterwards. To do this, you'll need to implement the interface in a class with only virtual function implementations and no member variables, then memcpy an instance of the class over the instance you get from GameUI.
I did this in my prototype engine to redirect filesystem calls:
https://github.com/SamVanheer/PrototypeEngine/blob/de14c82fff407bfa99e0153df8c4ec8710974df7/src/engine/CEngine.cpp#L107https://github.com/SamVanheer/PrototypeEngine/blob/de14c82fff407bfa99e0153df8c4ec8710974df7/src/engine/CFileSystemWrapper.hhttps://github.com/SamVanheer/PrototypeEngine/blob/de14c82fff407bfa99e0153df8c4ec8710974df7/src/engine/CFileSystemWrapper.cppYou'll need to create one instance to memcpy the original vtable from first, then memcpy yours in. Make sure all calls end up in the original eventually, because if GameUI's version calls its own methods using the vtable entry, it'll call yours instead. If it expects its own method to do something, this could cause crashes.
Also make sure you reverse this when the client shuts down so GameUI doesn't crash trying to call the client after it has unloaded.
Pseudo code:
//vtable points to original methods
CGameUIWrapper g_OriginalGameUI;
IGameUI* g_pGameUI = nullptr;
void RedirectGameUI()
{
g_pGameUI = (IGameUI *)gameUIFactory ("GameUI007", nullptr);
//sizeof( CGameUIWrapper ) is just the vtable pointer
memcpy( &g_OriginalGameUI, g_pGameUI, sizeof( g_OriginalGameUI ) );
CGameUIWrapper wrapper;
memcpy( g_pGameUI, &wrapper, sizeof( wrapper ) );
//g_pGameUI now calls CGameUIWrapper methods
}
void RestoreGameUI()
{
memcpy( g_pGameUI, &g_OriginalGameUI, sizeof( g_OriginalGameUI ) );
}
I can't guarantee that it'll work, it worked for me but my code completely overrides the original engine so there's no chance of code calling it beforehand.
It's your best chance at gaining control over the GameUI implementation without support from Valve.