Skip to content
Open
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
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/logic/CDownloadableResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class CDownloadableResource
RESOURCE_FILE_TYPE_CLIENT_CONFIG,
RESOURCE_FILE_TYPE_HTML,
RESOURCE_FILE_TYPE_CLIENT_FILE,
RESOURCE_FILE_TYPE_TRANSLATION,
RESOURCE_FILE_TYPE_GLOBAL_TRANSLATION,
};

public:
Expand Down
58 changes: 58 additions & 0 deletions Client/mods/deathmatch/logic/CGlobalTranslationItem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#include "CGlobalTranslationItem.h"
#include "CResource.h"
#include "CResourceTranslationManager.h"
#include "CClientGame.h"

CGlobalTranslationItem::CGlobalTranslationItem(CResource* resource, const char* src, uint uiDownloadSize, CChecksum serverChecksum)
: CResourceFile(resource, CDownloadableResource::RESOURCE_FILE_TYPE_GLOBAL_TRANSLATION, src, src, uiDownloadSize, serverChecksum, true)
{
m_providerResourceName = src ? src : "";
}

bool CGlobalTranslationItem::Start()
{
if (m_providerResourceName.empty())
{
CScriptDebugging* scriptDebugging = g_pClientGame->GetScriptDebugging();
SLuaDebugInfo debugInfo;
debugInfo.infoType = DEBUG_INFO_NONE;
debugInfo.strShortSrc = SString("[Resource: %s]", m_pResource->GetName());

scriptDebugging->LogError(debugInfo,
"Global translation: Empty provider resource name in meta.xml. "
"Check your <global-translation src=\"...\"/> tag.");
return false;
}

if (m_pResource->GetTranslationManager())
{
m_pResource->GetTranslationManager()->AddGlobalTranslationProvider(m_providerResourceName);
return true;
}

CScriptDebugging* scriptDebugging = g_pClientGame->GetScriptDebugging();
SLuaDebugInfo debugInfo;
debugInfo.infoType = DEBUG_INFO_NONE;
debugInfo.strShortSrc = SString("[Resource: %s]", m_pResource->GetName());

scriptDebugging->LogError(debugInfo,
"Global translation: Translation manager not available when adding provider '%s'. "
"This is an internal error - please report this issue.",
m_providerResourceName.c_str());
return false;
}

bool CGlobalTranslationItem::Stop()
{
return true;
}
27 changes: 27 additions & 0 deletions Client/mods/deathmatch/logic/CGlobalTranslationItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include "CResourceFile.h"
#include <string>

class CGlobalTranslationItem : public CResourceFile
{
public:
CGlobalTranslationItem(CResource* resource, const char* src, uint uiDownloadSize, CChecksum serverChecksum);

std::string GetProviderResourceName() const noexcept { return m_providerResourceName; }

bool Start();
bool Stop();

private:
std::string m_providerResourceName;
};
35 changes: 35 additions & 0 deletions Client/mods/deathmatch/logic/CPacketHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <game/CBuildingRemoval.h>
#include "net/SyncStructures.h"
#include "CServerInfo.h"
#include "CResourceTranslationItem.h"
#include "CGlobalTranslationItem.h"

using std::list;

Expand Down Expand Up @@ -5245,6 +5247,29 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
pDownloadableResource = pResource->AddConfigFile(szParsedChunkData, uiDownloadSize, chunkChecksum);

break;
case CDownloadableResource::RESOURCE_FILE_TYPE_TRANSLATION:
{
bool isPrimary = bitStream.ReadBit();
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_TRANSLATION,
szParsedChunkData, uiDownloadSize, chunkChecksum, true);
if (pDownloadableResource && isPrimary)
{
CResourceTranslationItem* translationItem = dynamic_cast<CResourceTranslationItem*>(pDownloadableResource);
if (translationItem)
{
pResource->SetTranslationPrimary(translationItem->GetLanguage());
}
}

break;
}
case CDownloadableResource::RESOURCE_FILE_TYPE_GLOBAL_TRANSLATION:
{
pDownloadableResource = pResource->AddResourceFile(CDownloadableResource::RESOURCE_FILE_TYPE_GLOBAL_TRANSLATION,
szParsedChunkData, uiDownloadSize, chunkChecksum, true);

break;
}
default:

break;
Expand Down Expand Up @@ -5293,6 +5318,16 @@ void CPacketHandler::Packet_ResourceStart(NetBitStreamInterface& bitStream)
}
}

// Read the global translation provider flag from server
bool isGlobalProvider = false;
if (bitStream.ReadBit(isGlobalProvider) && isGlobalProvider)
{
if (pResource->GetTranslationManager())
{
pResource->GetTranslationManager()->SetAsGlobalProvider(true);
}
}

if (!bFatalError)
{
g_pClientGame->GetResourceFileDownloadManager()->UpdatePendingDownloads();
Expand Down
77 changes: 76 additions & 1 deletion Client/mods/deathmatch/logic/CResource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#define DECLARE_PROFILER_SECTION_CResource
#include "profiler/SharedUtil.Profiler.h"
#include "CServerIdManager.h"
#include "CResourceTranslationItem.h"
#include "CGlobalTranslationItem.h"
#include "CGlobalTranslationManager.h"

using namespace std;

Expand Down Expand Up @@ -83,6 +86,8 @@ CResource::CResource(unsigned short usNetID, const char* szResourceName, CClient
// Move this after the CreateVirtualMachine line and heads will roll
m_bOOPEnabled = bEnableOOP;
m_iDownloadPriorityGroup = 0;

m_translationManager = std::make_unique<CResourceTranslationManager>(m_strResourceName.c_str());

m_pLuaVM = m_pLuaManager->CreateVirtualMachine(this, bEnableOOP);
if (m_pLuaVM)
Expand Down Expand Up @@ -183,7 +188,22 @@ CDownloadableResource* CResource::AddResourceFile(CDownloadableResource::eResour
return NULL;
}

CResourceFile* pResourceFile = new CResourceFile(this, resourceType, szFileName, strBuffer, uiDownloadSize, serverChecksum, bAutoDownload);
CResourceFile* pResourceFile = nullptr;

if (resourceType == CDownloadableResource::RESOURCE_FILE_TYPE_TRANSLATION)
{
bool isPrimary = m_translationPrimaryFlags.find(szFileName) != m_translationPrimaryFlags.end();
pResourceFile = new CResourceTranslationItem(this, szFileName, strBuffer, uiDownloadSize, serverChecksum, isPrimary);
}
else if (resourceType == CDownloadableResource::RESOURCE_FILE_TYPE_GLOBAL_TRANSLATION)
{
pResourceFile = new CGlobalTranslationItem(this, szFileName, uiDownloadSize, serverChecksum);
}
else
{
pResourceFile = new CResourceFile(this, resourceType, szFileName, strBuffer, uiDownloadSize, serverChecksum, bAutoDownload);
}

if (pResourceFile)
{
m_ResourceFiles.push_back(pResourceFile);
Expand Down Expand Up @@ -278,6 +298,8 @@ void CResource::Load()
}
}

LoadTranslations();

for (auto& list = m_NoClientCacheScriptList; !list.empty(); list.pop_front())
{
DECLARE_PROFILER_SECTION(OnPreLoadNoClientCacheScript)
Expand Down Expand Up @@ -328,6 +350,12 @@ void CResource::Load()
m_bActive = true;
m_bStarting = false;

// Register as global translation provider if marked as such
if (m_translationManager && m_translationManager->IsGlobalProvider())
{
CGlobalTranslationManager::GetSingleton().RegisterProvider(m_strResourceName.c_str(), m_translationManager.get());
}

// Did we get a resource root entity?
if (m_pResourceEntity)
{
Expand All @@ -354,6 +382,13 @@ void CResource::Stop()
{
m_bStarting = false;
m_bStopping = true;

// Unregister global translation provider if this resource was one
if (m_translationManager && m_translationManager->IsGlobalProvider())
{
CGlobalTranslationManager::GetSingleton().UnregisterProvider(m_strResourceName.c_str());
}

CLuaArguments Arguments;
Arguments.PushResource(this);
m_pResourceEntity->CallEvent("onClientResourceStop", Arguments, true);
Expand Down Expand Up @@ -521,3 +556,43 @@ void CResource::HandleDownloadedFileTrouble(CResourceFile* pResourceFile, bool b
g_pClientGame->TellServerSomethingImportant(bScript ? 1002 : 1013, strMessage, 4);
g_pCore->GetConsole()->Printf("Download error: %s", *strMessage);
}

bool CResource::LoadTranslations()
{
for (CResourceFile* resourceFile : m_ResourceFiles)
{
if (resourceFile->GetResourceType() == CDownloadableResource::RESOURCE_FILE_TYPE_TRANSLATION)
{
CResourceTranslationItem* translationItem = dynamic_cast<CResourceTranslationItem*>(resourceFile);
if (translationItem)
{
std::string fullPath = translationItem->GetName();
if (FileExists(fullPath.c_str()))
{
std::string language = translationItem->GetLanguage();
bool isPrimary = m_translationPrimaryFlags.find(language) != m_translationPrimaryFlags.end();
m_translationManager->LoadTranslation(fullPath, isPrimary);
}
}
}
else if (resourceFile->GetResourceType() == CDownloadableResource::RESOURCE_FILE_TYPE_GLOBAL_TRANSLATION)
{
CGlobalTranslationItem* globalTranslationItem = dynamic_cast<CGlobalTranslationItem*>(resourceFile);
if (globalTranslationItem)
{
globalTranslationItem->Start();
}
else
{
CScriptDebugging* scriptDebugging = g_pClientGame->GetScriptDebugging();
SLuaDebugInfo debugInfo;
debugInfo.infoType = DEBUG_INFO_NONE;
debugInfo.strShortSrc = SString("[Resource: %s]", m_strResourceName.c_str());

scriptDebugging->LogError(debugInfo,
"Failed to cast resource file to CGlobalTranslationItem");
}
}
}
return true;
}
8 changes: 8 additions & 0 deletions Client/mods/deathmatch/logic/CResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "CResourceFile.h"
#include "CResourceModelStreamer.h"
#include "CElementGroup.h"
#include "CResourceTranslationManager.h"
#include <list>

#define MAX_RESOURCE_NAME_LENGTH 255
Expand Down Expand Up @@ -99,6 +100,10 @@ class CResource
* @return A pointer to CResourceFile on success, null otherwise
*/
CResourceFile* GetResourceFile(const SString& relativePath) const;

CResourceTranslationManager* GetTranslationManager() const noexcept { return m_translationManager.get(); }
bool LoadTranslations();
void SetTranslationPrimary(const std::string& language) { m_translationPrimaryFlags[language] = true; }

void SetRemainingNoClientCacheScripts(unsigned short usRemaining) { m_usRemainingNoClientCacheScripts = usRemaining; }
void LoadNoClientCacheScript(const char* chunk, unsigned int length, const SString& strFilename);
Expand Down Expand Up @@ -154,4 +159,7 @@ class CResource
std::list<SNoClientCacheScript> m_NoClientCacheScriptList;

CResourceModelStreamer m_modelStreamer{};

std::unique_ptr<CResourceTranslationManager> m_translationManager;
std::map<std::string, bool> m_translationPrimaryFlags;
};
31 changes: 31 additions & 0 deletions Client/mods/deathmatch/logic/CResourceTranslationItem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: Client/mods/deathmatch/logic/CResourceTranslationItem.cpp
* PURPOSE: Resource translation item class
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#include "CResourceTranslationItem.h"
#include "CResource.h"
#include "CResourceTranslationManager.h"
#include "CLogger.h"
#include <filesystem>

CResourceTranslationItem::CResourceTranslationItem(CResource* resource, const char* name, const char* src, uint uiDownloadSize, CChecksum serverChecksum, bool isPrimary)
: CResourceFile(resource, RESOURCE_FILE_TYPE_TRANSLATION, name, src, uiDownloadSize, serverChecksum, true), m_isPrimary(isPrimary)
{
m_language = ExtractLanguageFromName();
}


std::string CResourceTranslationItem::ExtractLanguageFromName() const
{
// Cast away const since we know GetShortName() doesn't modify the object
std::filesystem::path path(const_cast<CResourceTranslationItem*>(this)->GetShortName());
return path.stem().string();
}
28 changes: 28 additions & 0 deletions Client/mods/deathmatch/logic/CResourceTranslationItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: Client/mods/deathmatch/logic/CResourceTranslationItem.h
* PURPOSE: Resource translation item class
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include "CResourceFile.h"

class CResourceTranslationItem : public CResourceFile
{
public:
CResourceTranslationItem(CResource* resource, const char* name, const char* src, uint uiDownloadSize, CChecksum serverChecksum, bool isPrimary = false);

const std::string& GetLanguage() const { return m_language; }
bool IsPrimary() const noexcept { return m_isPrimary; }

private:
std::string ExtractLanguageFromName() const;
std::string m_language;
bool m_isPrimary;
};
5 changes: 4 additions & 1 deletion Client/mods/deathmatch/logic/lua/CLuaManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

#include "StdInc.h"
#include "../luadefs/CLuaFireDefs.h"
#include "../luadefs/CLuaClientDefs.h"
#include "luadefs/CLuaBuildingDefs.h"
#include "../luadefs/CLuaTranslationDefsClient.h"
#include "../luadefs/CLuaVectorGraphicDefs.h"
#include "../luadefs/CLuaClientDefs.h"

using std::list;

Expand Down Expand Up @@ -283,4 +285,5 @@ void CLuaManager::LoadCFunctions()
CLuaClientDefs::LoadFunctions();
CLuaDiscordDefs::LoadFunctions();
CLuaBuildingDefs::LoadFunctions();
CLuaTranslationDefsClient::LoadFunctions();
}
Loading