Skip to content

Commit 9b0de0f

Browse files
Merge branch 'master' into default-skin-update
2 parents ee9ef5b + 7e22317 commit 9b0de0f

File tree

524 files changed

+22069
-16260
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

524 files changed

+22069
-16260
lines changed

Client/cefweb/CWebView.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ CWebView::~CWebView()
4141
g_pCore->GetWebCore()->SetFocusedWebView(nullptr);
4242
}
4343

44+
// Make sure we don't dead lock the CEF render thread
45+
ResumeCefThread();
46+
4447
// Ensure that CefRefPtr::~CefRefPtr doesn't try to release it twice (it has already been released in CWebView::OnBeforeClose)
45-
m_pWebView = nullptr;
48+
m_pWebView = nullptr;
4649

4750
OutputDebugLine("CWebView::~CWebView");
4851
}
@@ -77,6 +80,9 @@ void CWebView::CloseBrowser()
7780
// CefBrowserHost::CloseBrowser calls the destructor after the browser has been destroyed
7881
m_bBeingDestroyed = true;
7982

83+
// Make sure we don't dead lock the CEF render thread
84+
ResumeCefThread();
85+
8086
if (m_pWebView)
8187
m_pWebView->GetHost()->CloseBrowser(true);
8288
}
@@ -200,7 +206,7 @@ void CWebView::UpdateTexture()
200206

201207
auto pSurface = m_pWebBrowserRenderItem->m_pD3DRenderTargetSurface;
202208
if (m_bBeingDestroyed || !pSurface)
203-
return;
209+
m_RenderData.changed = m_RenderData.popupShown = false;
204210

205211
// Discard current buffer if size doesn't match
206212
// This happens when resizing the browser as OnPaint is called asynchronously
@@ -281,6 +287,9 @@ void CWebView::UpdateTexture()
281287
pSurface->UnlockRect();
282288
}
283289
}
290+
291+
m_RenderData.cefThreadState = ECefThreadState::Running;
292+
m_RenderData.cefThreadCv.notify_all();
284293
}
285294

286295
void CWebView::ExecuteJavascript(const SString& strJavascriptCode)
@@ -447,6 +456,8 @@ void CWebView::Resize(const CVector2D& size)
447456
// Send resize event to CEF
448457
if (m_pWebView)
449458
m_pWebView->GetHost()->WasResized();
459+
460+
ResumeCefThread();
450461
}
451462

452463
CVector2D CWebView::GetSize()
@@ -709,6 +720,10 @@ void CWebView::OnPaint(CefRefPtr<CefBrowser> browser, CefRenderHandler::PaintEle
709720
m_RenderData.height = height;
710721
m_RenderData.dirtyRects = dirtyRects;
711722
m_RenderData.changed = true;
723+
724+
// Wait for the main thread to handle drawing the texture
725+
m_RenderData.cefThreadState = ECefThreadState::Wait;
726+
m_RenderData.cefThreadCv.wait(lock, [&](){ return m_RenderData.cefThreadState == ECefThreadState::Running; });
712727
}
713728

714729
////////////////////////////////////////////////////////////////////
@@ -1069,3 +1084,14 @@ void CWebView::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser, CefRefPtr<CefF
10691084
// Show no context menu
10701085
model->Clear();
10711086
}
1087+
1088+
void CWebView::ResumeCefThread()
1089+
{
1090+
{
1091+
// It's recommended to unlock a mutex before the cv notifying to avoid a possible pessimization
1092+
std::unique_lock<std::mutex> lock(m_RenderData.dataMutex);
1093+
m_RenderData.cefThreadState = ECefThreadState::Running;
1094+
}
1095+
1096+
m_RenderData.cefThreadCv.notify_all();
1097+
}

Client/cefweb/CWebView.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030

3131
#define MTA_CEF_USERAGENT "Multi Theft Auto: San Andreas Client " MTA_DM_BUILDTAG_LONG
3232

33+
enum class ECefThreadState
34+
{
35+
Running = 0, // CEF thread is currently running
36+
Wait // CEF thread is waiting for the main thread
37+
};
38+
3339
class CWebView : public CWebViewInterface,
3440
private CefClient,
3541
private CefRenderHandler,
@@ -173,6 +179,8 @@ class CWebView : public CWebViewInterface,
173179
CefRefPtr<CefMenuModel> model) override;
174180

175181
private:
182+
void ResumeCefThread();
183+
176184
CefRefPtr<CefBrowser> m_pWebView;
177185
CWebBrowserItem* m_pWebBrowserRenderItem;
178186

@@ -192,6 +200,8 @@ class CWebView : public CWebViewInterface,
192200
{
193201
bool changed = false;
194202
std::mutex dataMutex;
203+
ECefThreadState cefThreadState = ECefThreadState::Running;
204+
std::condition_variable cefThreadCv;
195205

196206
const void* buffer;
197207
int width, height;
0 Bytes
Binary file not shown.

Client/mods/deathmatch/logic/CClientVectorGraphicDisplay.cpp

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ void CClientVectorGraphicDisplay::Render()
4242
if (HasUpdated())
4343
{
4444
m_pVectorGraphic->OnUpdate();
45-
}
46-
45+
}
4746
}
4847

4948
void CClientVectorGraphicDisplay::UpdateTexture()
@@ -52,46 +51,41 @@ void CClientVectorGraphicDisplay::UpdateTexture()
5251
return;
5352

5453
Document* svgDocument = m_pVectorGraphic->GetSVGDocument();
55-
56-
if (svgDocument == nullptr)
54+
if (!svgDocument)
5755
return;
5856

5957
CVectorGraphicItem* pVectorGraphicItem = m_pVectorGraphic->GetRenderItem();
60-
6158
if (!pVectorGraphicItem)
6259
return;
6360

6461
IDirect3DSurface9* surface = m_pVectorGraphic->GetRenderItem()->m_pD3DRenderTargetSurface;
65-
6662
if (!surface)
6763
return;
6864

69-
IDirect3DDevice9* device = pVectorGraphicItem->m_pDevice;
70-
71-
uint width = pVectorGraphicItem->m_uiSizeX;
72-
uint height = pVectorGraphicItem->m_uiSizeY;
73-
74-
Bitmap bitmap = svgDocument->renderToBitmap(width, height);
65+
Bitmap bitmap = svgDocument->renderToBitmap(pVectorGraphicItem->m_uiSizeX, pVectorGraphicItem->m_uiSizeY);
66+
if (!bitmap.valid())
67+
return;
7568

7669
// Lock surface
7770
D3DLOCKED_RECT LockedRect;
78-
surface->LockRect(&LockedRect, nullptr, 0);
71+
if (SUCCEEDED(surface->LockRect(&LockedRect, nullptr, D3DLOCK_DISCARD)))
72+
{
73+
auto surfaceData = static_cast<byte*>(LockedRect.pBits);
74+
auto sourceData = static_cast<const byte*>(bitmap.data());
7975

80-
auto surfaceData = static_cast<byte*>(LockedRect.pBits);
81-
auto sourceData = static_cast<const byte*>(bitmap.data());
76+
for (uint32_t y = 0; y < bitmap.height(); ++y)
77+
{
78+
memcpy(surfaceData, sourceData, bitmap.width() * 4); // 4 bytes per pixel
8279

83-
for (uint32_t y = 0; y < bitmap.height(); ++y)
84-
{
85-
memcpy(surfaceData, sourceData, bitmap.width() * 4); // 4 bytes per pixel
80+
// advance row pointers
81+
sourceData += bitmap.stride();
82+
surfaceData += LockedRect.Pitch;
83+
}
8684

87-
// advance row pointers
88-
sourceData += bitmap.stride();
89-
surfaceData += LockedRect.Pitch;
85+
// Unlock surface
86+
surface->UnlockRect();
9087
}
9188

92-
// Unlock surface
93-
surface->UnlockRect();
94-
9589
m_bHasUpdated = false;
9690
}
9791

@@ -101,25 +95,22 @@ void CClientVectorGraphicDisplay::ClearTexture()
10195
return;
10296

10397
CVectorGraphicItem* pVectorGraphicItem = m_pVectorGraphic->GetRenderItem();
104-
10598
if (!pVectorGraphicItem)
10699
return;
107100

108101
IDirect3DSurface9* surface = pVectorGraphicItem->m_pD3DRenderTargetSurface;
109-
110102
if (!surface)
111103
return;
112104

113-
IDirect3DDevice9* device = pVectorGraphicItem->m_pDevice;
114-
115105
// Lock surface
116106
D3DLOCKED_RECT LockedRect;
117-
surface->LockRect(&LockedRect, nullptr, 0);
118-
119-
device->ColorFill(surface, nullptr, D3DCOLOR_ARGB(0, 0, 0, 0));
107+
if (SUCCEEDED(surface->LockRect(&LockedRect, nullptr, D3DLOCK_DISCARD)))
108+
{
109+
std::memset(LockedRect.pBits, 0x0, LockedRect.Pitch * pVectorGraphicItem->m_uiSurfaceSizeY);
120110

121-
// Unlock surface
122-
surface->UnlockRect();
111+
// Unlock surface
112+
surface->UnlockRect();
113+
}
123114

124115
m_bIsCleared = true;
125116
}

Client/mods/deathmatch/logic/CPacketHandler.cpp

Lines changed: 86 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4999,6 +4999,8 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
49994999
return;
50005000
}
50015001

5002+
bool bFatalError = false;
5003+
50025004
CResource* pResource = g_pClientGame->m_pResourceManager->Add(usResourceID, szResourceName, pResourceEntity, pResourceDynamicEntity, strMinServerReq,
50035005
strMinClientReq, bEnableOOP);
50045006
if (pResource)
@@ -5047,61 +5049,80 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
50475049
}
50485050
szChunkData[ucChunkSize] = NULL;
50495051

5050-
bitStream.Read(ucChunkSubType);
5051-
bitStream.Read(chunkChecksum.ulCRC);
5052-
bitStream.Read((char*)chunkChecksum.md5.data, sizeof(chunkChecksum.md5.data));
5053-
bitStream.Read(dChunkDataSize);
5054-
5055-
uint uiDownloadSize = (uint)dChunkDataSize;
5056-
uiTotalSizeProcessed += uiDownloadSize;
5057-
if (uiTotalSizeProcessed / 1024 / 1024 > 50)
5058-
g_pCore->UpdateDummyProgress(uiTotalSizeProcessed / 1024 / 1024, " MB");
5059-
5060-
// Create the resource downloadable
5061-
CDownloadableResource* pDownloadableResource = NULL;
5062-
switch (ucChunkSubType)
5052+
std::string strChunkData = szChunkData;
5053+
// make the full file path (c:/path/to/mods/deathmatch/resources/resource/)
5054+
std::string strMetaPathTemp;
5055+
std::string strResPathTemp = pResource->GetResourceDirectoryPath(ACCESS_PUBLIC, strMetaPathTemp);
5056+
std::filesystem::path fsResPath = std::filesystem::path(strResPathTemp).lexically_normal();
5057+
std::string strResPath = fsResPath.string();
5058+
// make the full file path (c:/path/to/mods/deathmatch/resources/resource/file.lua)
5059+
std::string strResFilePathTemp = strResPath + static_cast<char>(std::filesystem::path::preferred_separator) + strChunkData;
5060+
std::filesystem::path fsResFilePath = std::filesystem::path(strResFilePathTemp).lexically_normal();
5061+
std::string strResFilePath = fsResFilePath.string();
5062+
// check that full file path contains full resource path
5063+
if (strResFilePath.rfind(strResPath.c_str(), 0) != 0)
5064+
{
5065+
bFatalError = true;
5066+
AddReportLog(2081, SString("Path %s (expected %s)", strResFilePath.c_str(), strResPath.c_str()));
5067+
}
5068+
else
50635069
{
5064-
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE:
5070+
bitStream.Read(ucChunkSubType);
5071+
bitStream.Read(chunkChecksum.ulCRC);
5072+
bitStream.Read((char*)chunkChecksum.md5.data, sizeof(chunkChecksum.md5.data));
5073+
bitStream.Read(dChunkDataSize);
5074+
5075+
uint uiDownloadSize = (uint)dChunkDataSize;
5076+
uiTotalSizeProcessed += uiDownloadSize;
5077+
if (uiTotalSizeProcessed / 1024 / 1024 > 50)
5078+
g_pCore->UpdateDummyProgress(uiTotalSizeProcessed / 1024 / 1024, " MB");
5079+
5080+
// Create the resource downloadable
5081+
CDownloadableResource* pDownloadableResource = NULL;
5082+
switch (ucChunkSubType)
50655083
{
5066-
bool bDownload = bitStream.ReadBit();
5067-
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE, szChunkData,
5068-
uiDownloadSize, chunkChecksum, bDownload);
5069-
5070-
break;
5071-
}
5072-
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT:
5073-
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT, szChunkData,
5074-
uiDownloadSize, chunkChecksum, true);
5084+
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE:
5085+
{
5086+
bool bDownload = bitStream.ReadBit();
5087+
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_FILE, szChunkData,
5088+
uiDownloadSize, chunkChecksum, bDownload);
50755089

5076-
break;
5077-
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_CONFIG:
5078-
pDownloadableResource = pResource->AddConfigFile(szChunkData, uiDownloadSize, chunkChecksum);
5090+
break;
5091+
}
5092+
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT:
5093+
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_SCRIPT, szChunkData,
5094+
uiDownloadSize, chunkChecksum, true);
50795095

5080-
break;
5081-
default:
5096+
break;
5097+
case CDownloadableResource::RESOURCE_FILE_TYPE_CLIENT_CONFIG:
5098+
pDownloadableResource = pResource->AddConfigFile(szChunkData, uiDownloadSize, chunkChecksum);
50825099

5083-
break;
5084-
}
5100+
break;
5101+
default:
50855102

5086-
// Does the Client and Server checksum differ?
5087-
if (pDownloadableResource && !pDownloadableResource->DoesClientAndServerChecksumMatch())
5088-
{
5089-
// Delete the file that already exists
5090-
FileDelete(pDownloadableResource->GetName());
5091-
if (FileExists(pDownloadableResource->GetName()))
5092-
{
5093-
SString strMessage("Unable to delete old file %s", *ConformResourcePath(pDownloadableResource->GetName()));
5094-
g_pClientGame->TellServerSomethingImportant(1009, strMessage);
5103+
break;
50955104
}
50965105

5097-
// Is it downloadable now?
5098-
if (pDownloadableResource->IsAutoDownload())
5106+
// Does the Client and Server checksum differ?
5107+
if (pDownloadableResource && !pDownloadableResource->DoesClientAndServerChecksumMatch())
50995108
{
5100-
// Make sure the directory exists
5101-
MakeSureDirExists(pDownloadableResource->GetName());
5109+
// Delete the file that already exists
5110+
FileDelete(pDownloadableResource->GetName());
5111+
if (FileExists(pDownloadableResource->GetName()))
5112+
{
5113+
SString strMessage("Unable to delete old file %s", *ConformResourcePath(pDownloadableResource->GetName()));
5114+
g_pClientGame->TellServerSomethingImportant(1009, strMessage);
5115+
}
51025116

5103-
// Queue the file to be downloaded
5104-
g_pClientGame->GetResourceFileDownloadManager()->AddPendingFileDownload(pDownloadableResource);
5117+
// Is it downloadable now?
5118+
if (pDownloadableResource->IsAutoDownload())
5119+
{
5120+
// Make sure the directory exists
5121+
MakeSureDirExists(pDownloadableResource->GetName());
5122+
5123+
// Queue the file to be downloaded
5124+
g_pClientGame->GetResourceFileDownloadManager()->AddPendingFileDownload(pDownloadableResource);
5125+
}
51055126
}
51065127
}
51075128
}
@@ -5116,17 +5137,25 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
51165137
delete[] szChunkData;
51175138
szChunkData = NULL;
51185139
}
5119-
}
51205140

5121-
g_pClientGame->GetResourceFileDownloadManager()->UpdatePendingDownloads();
5141+
if (bFatalError)
5142+
{
5143+
break;
5144+
}
5145+
}
51225146

5123-
// Are there any resources to being downloaded?
5124-
if (!g_pClientGame->GetResourceFileDownloadManager()->IsTransferringInitialFiles())
5147+
if (!bFatalError)
51255148
{
5126-
// Load the resource now
5127-
if (pResource->CanBeLoaded())
5149+
g_pClientGame->GetResourceFileDownloadManager()->UpdatePendingDownloads();
5150+
5151+
// Are there any resources to being downloaded?
5152+
if (!g_pClientGame->GetResourceFileDownloadManager()->IsTransferringInitialFiles())
51285153
{
5129-
pResource->Load();
5154+
// Load the resource now
5155+
if (pResource->CanBeLoaded())
5156+
{
5157+
pResource->Load();
5158+
}
51305159
}
51315160
}
51325161
}
@@ -5136,6 +5165,11 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
51365165

51375166
g_pCore->UpdateDummyProgress(0);
51385167
totalSizeProcessedResetTimer.Reset();
5168+
5169+
if (bFatalError)
5170+
{
5171+
RaiseFatalError(2081);
5172+
}
51395173
}
51405174

51415175
void CPacketHandler::Packet_ResourceStop(NetBitStreamInterface& bitStream)

0 commit comments

Comments
 (0)