Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Client/core/CConsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ CConsole::CConsole(CGUI* pManager, CGUIElement* pParent)

m_pHistory->SetTextChangedHandler(GUI_CALLBACK(&CConsole::History_OnTextChanged, this));

// Load the console history from a file
m_pConsoleHistory->LoadFromFile(MTA_CONSOLE_INPUT_LOG_PATH);
// Load the console history from a file - use -cl2 suffix for secondary client
SString strInputLogPath = MTA_CONSOLE_INPUT_LOG_PATH;
if (g_pCore->IsSecondaryClient())
{
strInputLogPath.Replace(".log", "-cl2.log");
}
m_pConsoleHistory->LoadFromFile(strInputLogPath);
}

CConsole::~CConsole()
Expand Down
9 changes: 7 additions & 2 deletions Client/core/CConsoleLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ CConsoleLogger* CSingleton<CConsoleLogger>::m_pSingleton = NULL;

CConsoleLogger::CConsoleLogger()
{
// Create file name
m_strFilename = CalcMTASAPath(MTA_CONSOLE_LOG_PATH);
// Create file name - use -cl2 suffix for secondary client
SString strLogPath = MTA_CONSOLE_LOG_PATH;
if (g_pCore->IsSecondaryClient())
{
strLogPath.Replace(".log", "-cl2.log");
}
m_strFilename = CalcMTASAPath(strLogPath);

// Cycle if over size (100KB, 5 backup files)
CycleFile(m_strFilename, 100, 5);
Expand Down
54 changes: 52 additions & 2 deletions Client/core/CCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,20 @@ const char* CCore::GetModInstallRoot(const char* szModName)
return m_strModInstallRoot;
}

bool CCore::IsSecondaryClient()
{
static bool bChecked = false;
static bool bIsSecondary = false;

if (!bChecked)
{
bIsSecondary = (strstr(GetCommandLine(), "-cl2") != NULL);
bChecked = true;
}

return bIsSecondary;
}

void CCore::ForceCursorVisible(bool bVisible, bool bToggleControls)
{
m_bCursorToggleControls = bToggleControls;
Expand Down Expand Up @@ -870,6 +884,23 @@ void CCore::ApplyHooks()
// Remove useless DirectPlay dependency (dpnhpast.dll) @ 0x745701
// We have to patch here as multiplayer_sa and game_sa are loaded too late
DetourLibraryFunction("kernel32.dll", "LoadLibraryA", Win32LoadLibraryA, SkipDirectPlay_LoadLibraryA);

// Special thanks for botder too [https://github.com/multitheftauto/mtasa-blue/commit/b08948fcf46746c9d74503a0889996575f93cde5]
// Disable code that disallows multiple instances of GTA:SA
// Disable `if (IsAppAlreadyRunning())` in WinMain
{
DWORD oldProtect;
VirtualProtect(reinterpret_cast<void*>(0x74872D), 9, PAGE_READWRITE, &oldProtect);
memcpy(reinterpret_cast<void*>(0x74872D), "\x90\x90\x90\x90\x90\x90\x90\x90\x90", 9);
VirtualProtect(reinterpret_cast<void*>(0x74872D), 9, oldProtect, &oldProtect);
}
// Create an unnamed semaphore in CdStreamInitThread.
{
DWORD oldProtect;
VirtualProtect(reinterpret_cast<void*>(0x406945), 5, PAGE_READWRITE, &oldProtect);
memcpy(reinterpret_cast<void*>(0x406945), "\x6A\x00\x90\x90\x90", 5);
VirtualProtect(reinterpret_cast<void*>(0x406945), 5, oldProtect, &oldProtect);
}
}

bool UsingAltD3DSetup()
Expand Down Expand Up @@ -1093,8 +1124,27 @@ void CCore::CreateXML()

if (!m_pConfigFile)
{
// Load config XML file
m_pConfigFile = m_pXML->CreateXML(CalcMTASAPath(MTA_CONFIG_PATH));
// Load config XML file - use -cl2 suffix for secondary client
SString strConfigPath = MTA_CONFIG_PATH;
bool bIsSecondary = IsSecondaryClient();

if (bIsSecondary)
{
strConfigPath = strConfigPath.Replace(".xml", "-cl2.xml");

// If CL2 config doesn't exist, copy from the primary config
SString strFullPath = CalcMTASAPath(strConfigPath);
if (!FileExists(strFullPath))
{
SString strPrimaryConfig = CalcMTASAPath(MTA_CONFIG_PATH);
if (FileExists(strPrimaryConfig))
{
FileCopy(strPrimaryConfig, strFullPath);
}
}
}

m_pConfigFile = m_pXML->CreateXML(CalcMTASAPath(strConfigPath));
if (!m_pConfigFile)
{
assert(false);
Expand Down
1 change: 1 addition & 0 deletions Client/core/CCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class CCore : public CCoreInterface, public CSingleton<CCore>
bool IsOfflineMod() { return m_bIsOfflineMod; }
const char* GetModInstallRoot(const char* szModName);
bool CheckDiskSpace(uint uiResourcesPathMinMB = 10, uint uiDataPathMinMB = 10);
bool IsSecondaryClient();

// Subsystems
void CreateGame();
Expand Down
21 changes: 20 additions & 1 deletion Client/core/CSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4964,7 +4964,26 @@ void CSettings::SetChatColorValues(eChatColorType eType, CColor pColor)

void CSettings::LoadChatPresets()
{
CXMLFile* pPresetsFile = CCore::GetSingleton().GetXML()->CreateXML(CalcMTASAPath(CHAT_PRESETS_PATH));
SString strPresetsPath = CHAT_PRESETS_PATH;
bool bIsSecondary = g_pCore->IsSecondaryClient();

if (bIsSecondary)
{
strPresetsPath = strPresetsPath.Replace(".xml", "-cl2.xml");

// If CL2 presets file doesn't exist, copy from the primary
SString strFullPath = CalcMTASAPath(strPresetsPath);
if (!FileExists(strFullPath))
{
SString strPrimaryPresets = CalcMTASAPath(CHAT_PRESETS_PATH);
if (FileExists(strPrimaryPresets))
{
FileCopy(strPrimaryPresets, strFullPath);
}
}
}

CXMLFile* pPresetsFile = CCore::GetSingleton().GetXML()->CreateXML(CalcMTASAPath(strPresetsPath));
if (pPresetsFile && pPresetsFile->Parse())
{
CXMLNode* pPresetsRoot = pPresetsFile->GetRootNode();
Expand Down
28 changes: 28 additions & 0 deletions Client/core/CVersionUpdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,18 @@ void CVersionUpdater::DoPulse()
///////////////////////////////////////////////////////////////
void CVersionUpdater::InitiateUpdate(const SString& strType, const SString& strData, const SString& strHost)
{
// Disable server-initiated updates for secondary client
if (CCore::GetSingleton().IsSecondaryClient())
return;

// Don't allow update if CL2 is running
HANDLE hCL2Mutex = OpenMutexA(SYNCHRONIZE, FALSE, "Global\\{4962AF5F-5D82-412D-9CCA-AB8BB9DBD354}");
if (hCL2Mutex)
{
CloseHandle(hCL2Mutex);
return;
}

if (strType == "Mandatory")
{
CCore::GetSingleton().RemoveMessageBox();
Expand Down Expand Up @@ -615,6 +627,22 @@ void CVersionUpdater::InitiateDataFilesFix()
///////////////////////////////////////////////////////////////
void CVersionUpdater::InitiateManualCheck()
{
// Disable update checking for secondary client
if (CCore::GetSingleton().IsSecondaryClient())
{
CCore::GetSingleton().ShowMessageBox(_("Information"), _("Update checking is disabled in secondary client"), MB_BUTTON_OK | MB_ICON_INFO);
return;
}

// Don't allow update if CL2 is running
HANDLE hCL2Mutex = OpenMutexA(SYNCHRONIZE, FALSE, "Global\\{4962AF5F-5D82-412D-9CCA-AB8BB9DBD354}");
if (hCL2Mutex)
{
CloseHandle(hCL2Mutex);
CCore::GetSingleton().ShowMessageBox(_("Information"), _("Can't check for updates while secondary client is running"), MB_BUTTON_OK | MB_ICON_INFO);
return;
}

if (GetQuestionBox().IsVisible())
{
// Bring to the front
Expand Down
10 changes: 6 additions & 4 deletions Client/core/DXHook/CProxyDirect3D9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,11 @@ HRESULT CProxyDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND
pPresentationParameters->PresentationInterval));

// Change the window title to MTA: San Andreas
bool bIsSecondaryClient = g_pCore->IsSecondaryClient();
#ifdef MTA_DEBUG
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16("MTA: San Andreas [DEBUG]").c_str());
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16(bIsSecondaryClient ? "MTA: San Andreas [CL2-DEBUG]" : "MTA: San Andreas [DEBUG]").c_str());
#else
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16("MTA: San Andreas").c_str());
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16(bIsSecondaryClient ? "MTA: San Andreas [CL2]" : "MTA: San Andreas").c_str());
#endif

// Set dark titlebar if needed
Expand Down Expand Up @@ -1348,10 +1349,11 @@ HRESULT CCore::OnPostCreateDevice(HRESULT hResult, IDirect3D9* pDirect3D, UINT A
AddCapsReport(Adapter, pDirect3D, *ppReturnedDeviceInterface, true);

// Change the window title to MTA: San Andreas
bool bIsSecondaryClient = g_pCore->IsSecondaryClient();
#ifdef MTA_DEBUG
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16("MTA: San Andreas [DEBUG]").c_str());
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16(bIsSecondaryClient ? "MTA: San Andreas [CL2-DEBUG]" : "MTA: San Andreas [DEBUG]").c_str());
#else
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16("MTA: San Andreas").c_str());
SetWindowTextW(hFocusWindow, MbUTF8ToUTF16(bIsSecondaryClient ? "MTA: San Andreas [CL2]" : "MTA: San Andreas").c_str());
#endif

// Log graphic card name
Expand Down
30 changes: 27 additions & 3 deletions Client/core/ServerBrowser/CServerCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,25 @@ CServerCache::~CServerCache()
///////////////////////////////////////////////////////////////
bool CServerCache::LoadServerCache()
{
// Load config XML file
CXMLFile* m_pConfigFile = CCore::GetSingleton().GetXML()->CreateXML(CalcMTASAPath(MTA_SERVER_CACHE_PATH));
// Load config XML file - use -cl2 suffix for secondary client
SString strCachePath = MTA_SERVER_CACHE_PATH;
if (g_pCore->IsSecondaryClient())
{
strCachePath = strCachePath.Replace(".xml", "-cl2.xml");

// If CL2 cache doesn't exist, copy from the primary cache
SString strFullPath = CalcMTASAPath(strCachePath);
if (!FileExists(strFullPath))
{
SString strPrimaryCache = CalcMTASAPath(MTA_SERVER_CACHE_PATH);
if (FileExists(strPrimaryCache))
{
FileCopy(strPrimaryCache, strFullPath);
}
}
}

CXMLFile* m_pConfigFile = CCore::GetSingleton().GetXML()->CreateXML(CalcMTASAPath(strCachePath));
if (!m_pConfigFile)
return false;
m_pConfigFile->Parse();
Expand Down Expand Up @@ -269,7 +286,14 @@ DWORD WINAPI CServerCache::StaticThreadProc(LPVOID lpdwThreadParam)
///////////////////////////////////////////////////////////////
void CServerCache::StaticSaveServerCache()
{
CXMLFile* m_pConfigFile = CCore::GetSingleton().GetXML()->CreateXML(CalcMTASAPath(MTA_SERVER_CACHE_PATH));
// Use -cl2 suffix for secondary client
SString strCachePath = MTA_SERVER_CACHE_PATH;
if (g_pCore->IsSecondaryClient())
{
strCachePath = strCachePath.Replace(".xml", "-cl2.xml");
}

CXMLFile* m_pConfigFile = CCore::GetSingleton().GetXML()->CreateXML(CalcMTASAPath(strCachePath));
if (!m_pConfigFile)
return;
m_pConfigFile->Parse();
Expand Down
1 change: 1 addition & 0 deletions Client/loader/Main.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define STEAM_GTA_EXE_NAME "gta-sa.exe"
#define MTA_GTA_KNOWN_FILE_NAME "models\\gta3.img"
#define MTA_GUID "Global\\{4962AF5F-5D82-412D-9CCA-AB8BB9DBD353}"
#define MTA_GUID_CL2 "Global\\{4962AF5F-5D82-412D-9CCA-AB8BB9DBD354}"
#define URI_CONNECT 1
#define MTA_EXE_NAME_RELEASE "Multi Theft Auto.exe"
#define LOADER_PROXY_DLL_NAME "mtasa.dll"
Expand Down
7 changes: 6 additions & 1 deletion Client/loader/MainFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,8 @@ void HandleNotUsedMainMenu()

// Check current display mode in coreconfig.xml
{
SString strCoreConfigFilename = CalcMTASAPath(PathJoin("mta", "config", "coreconfig.xml"));
SString strCoreConfigName = IsSecondaryClient() ? "coreconfig-cl2.xml" : "coreconfig.xml";
SString strCoreConfigFilename = CalcMTASAPath(PathJoin("mta", "config", strCoreConfigName));
SString strCoreConfig;
FileLoad(strCoreConfigFilename, strCoreConfig);
SString strWindowed = strCoreConfig.SplitRight("<display_windowed>").Left(1);
Expand Down Expand Up @@ -707,6 +708,10 @@ void PostRunWatchDogs(int iReturnCode)
//////////////////////////////////////////////////////////
void HandleIfGTAIsAlreadyRunning()
{
// Skip GTA check for secondary client to allow multiple GTA instances
if (IsSecondaryClient())
return;

if (IsGTARunning())
{
if (MessageBoxUTF8(0,
Expand Down
52 changes: 50 additions & 2 deletions Client/loader/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ namespace fs = std::filesystem;
static SString g_strMTASAPath;
static SString g_strGTAPath;
static HANDLE g_hMutex = NULL;

// Check if secondary client mode is active
bool IsSecondaryClient()
{
static int iResult = -1;
if (iResult == -1)
{
iResult = (strstr(GetCommandLine(), "-cl2") != NULL) ? 1 : 0;
}
return iResult == 1;
}
static HMODULE hLibraryModule = NULL;
HINSTANCE g_hInstance = NULL;

Expand Down Expand Up @@ -321,6 +332,14 @@ std::vector<DWORD> GetGTAProcessList()
///////////////////////////////////////////////////////////////////////////
bool IsGTARunning()
{
// Don't report GTA as running if CL2 is active (to allow coexistence)
HANDLE hCL2Mutex = OpenMutexA(SYNCHRONIZE, FALSE, MTA_GUID_CL2);
if (hCL2Mutex)
{
CloseHandle(hCL2Mutex);
return false;
}

return !GetGTAProcessList().empty();
}

Expand All @@ -333,6 +352,17 @@ bool IsGTARunning()
///////////////////////////////////////////////////////////////////////////
void TerminateGTAIfRunning()
{
if (IsSecondaryClient())
return;

// Don't terminate GTA if CL2 is running
HANDLE hCL2Mutex = OpenMutexA(SYNCHRONIZE, FALSE, MTA_GUID_CL2);
if (hCL2Mutex)
{
CloseHandle(hCL2Mutex);
return;
}

std::vector<DWORD> processIdList = GetGTAProcessList();

// Try to stop all GTA process id's
Expand Down Expand Up @@ -395,6 +425,17 @@ bool IsOtherMTARunning()
///////////////////////////////////////////////////////////////////////////
void TerminateOtherMTAIfRunning()
{
if (IsSecondaryClient())
return;

// Don't terminate other MTA if CL2 is running
HANDLE hCL2Mutex = OpenMutexA(SYNCHRONIZE, FALSE, MTA_GUID_CL2);
if (hCL2Mutex)
{
CloseHandle(hCL2Mutex);
return;
}

std::vector<DWORD> processIdList = GetOtherMTAProcessList();

if (processIdList.size())
Expand Down Expand Up @@ -1193,12 +1234,16 @@ bool TerminateProcess(DWORD dwProcessID, uint uiExitCode)
//
// CreateSingleInstanceMutex
//
//
// Create mutex to prevent multiple instances
// Secondary client (-cl2) uses a different GUID
//
///////////////////////////////////////////////////////////////////////////
bool CreateSingleInstanceMutex()
{
HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT(MTA_GUID));
// Use different GUID for secondary client
const char* szGuid = IsSecondaryClient() ? MTA_GUID_CL2 : MTA_GUID;

HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT(szGuid));

if (GetLastError() == ERROR_ALREADY_EXISTS)
{
Expand All @@ -1220,6 +1265,9 @@ bool CreateSingleInstanceMutex()
///////////////////////////////////////////////////////////////////////////
void ReleaseSingleInstanceMutex()
{
if (IsSecondaryClient())
return;

// assert(g_hMutex);
CloseHandle(g_hMutex);
g_hMutex = NULL;
Expand Down
1 change: 1 addition & 0 deletions Client/loader/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct SPEFileOffsets

void TerminateGTAIfRunning();
bool IsGTARunning();
bool IsSecondaryClient();
void TerminateOtherMTAIfRunning();
bool IsOtherMTARunning();

Expand Down
Loading