refactor: extract LocalizationManager, ArchiveManager, SkinManager from Game

This commit is contained in:
MatthewBeshay 2026-04-04 18:12:43 +11:00 committed by Tropical
parent 0c7800d28b
commit d61d3cddab
9 changed files with 2180 additions and 1899 deletions

View file

@ -0,0 +1,128 @@
#include "app/common/ArchiveManager.h"
#include <mutex>
#include <string>
#include "app/common/UI/All Platforms/ArchiveFile.h"
#include "app/linux/LinuxGame.h"
#include "java/File.h"
#include "minecraft/client/Minecraft.h"
#include "minecraft/client/skins/TexturePack.h"
#include "minecraft/client/skins/TexturePackRepository.h"
#include "platform/PlatformServices.h"
#include "platform/PlatformTypes.h"
ArchiveManager::ArchiveManager()
: m_mediaArchive(nullptr), m_dwRequiredTexturePackID(0) {}
void ArchiveManager::loadMediaArchive() {
std::wstring mediapath = L"";
#if _WINDOWS64
mediapath = L"Common\\Media\\MediaWindows64.arc";
#elif __linux__
mediapath = L"app/common/Media/MediaLinux.arc";
#endif
if (!mediapath.empty()) {
#if defined(__linux__)
std::wstring exeDirW = PlatformFileIO.getBasePath().wstring();
std::wstring candidate = exeDirW + File::pathSeparator + mediapath;
if (File(candidate).exists()) {
m_mediaArchive = new ArchiveFile(File(candidate));
} else {
m_mediaArchive = new ArchiveFile(File(mediapath));
}
#else
m_mediaArchive = new ArchiveFile(File(mediapath));
#endif
}
}
int ArchiveManager::getArchiveFileSize(const std::wstring& filename) {
TexturePack* tPack = nullptr;
Minecraft* pMinecraft = Minecraft::GetInstance();
if (pMinecraft && pMinecraft->skins)
tPack = pMinecraft->skins->getSelected();
if (tPack && tPack->hasData() && tPack->getArchiveFile() &&
tPack->getArchiveFile()->hasFile(filename)) {
return tPack->getArchiveFile()->getFileSize(filename);
} else
return m_mediaArchive->getFileSize(filename);
}
bool ArchiveManager::hasArchiveFile(const std::wstring& filename) {
TexturePack* tPack = nullptr;
Minecraft* pMinecraft = Minecraft::GetInstance();
if (pMinecraft && pMinecraft->skins)
tPack = pMinecraft->skins->getSelected();
if (tPack && tPack->hasData() && tPack->getArchiveFile() &&
tPack->getArchiveFile()->hasFile(filename))
return true;
else
return m_mediaArchive->hasFile(filename);
}
std::vector<uint8_t> ArchiveManager::getArchiveFile(
const std::wstring& filename) {
TexturePack* tPack = nullptr;
Minecraft* pMinecraft = Minecraft::GetInstance();
if (pMinecraft && pMinecraft->skins)
tPack = pMinecraft->skins->getSelected();
if (tPack && tPack->hasData() && tPack->getArchiveFile() &&
tPack->getArchiveFile()->hasFile(filename)) {
return tPack->getArchiveFile()->getFile(filename);
} else
return m_mediaArchive->getFile(filename);
}
void ArchiveManager::addMemoryTPDFile(int iConfig, std::uint8_t* pbData,
unsigned int byteCount) {
std::lock_guard<std::mutex> lock(csMemTPDLock);
PMEMDATA pData = nullptr;
auto it = m_MEM_TPD.find(iConfig);
if (it == m_MEM_TPD.end()) {
pData = new MEMDATA();
pData->pbData = pbData;
pData->byteCount = byteCount;
pData->ucRefCount = 1;
m_MEM_TPD[iConfig] = pData;
}
}
void ArchiveManager::removeMemoryTPDFile(int iConfig) {
std::lock_guard<std::mutex> lock(csMemTPDLock);
PMEMDATA pData = nullptr;
auto it = m_MEM_TPD.find(iConfig);
if (it != m_MEM_TPD.end()) {
pData = m_MEM_TPD[iConfig];
delete pData;
m_MEM_TPD.erase(iConfig);
}
}
int ArchiveManager::getTPConfigVal(wchar_t* pwchDataFile) { return -1; }
bool ArchiveManager::isFileInTPD(int iConfig) {
bool val = false;
{
std::lock_guard<std::mutex> lock(csMemTPDLock);
auto it = m_MEM_TPD.find(iConfig);
if (it != m_MEM_TPD.end()) val = true;
}
return val;
}
void ArchiveManager::getTPD(int iConfig, std::uint8_t** ppbData,
unsigned int* pByteCount) {
std::lock_guard<std::mutex> lock(csMemTPDLock);
auto it = m_MEM_TPD.find(iConfig);
if (it != m_MEM_TPD.end()) {
PMEMDATA pData = (*it).second;
*ppbData = pData->pbData;
*pByteCount = pData->byteCount;
}
}

View file

@ -0,0 +1,54 @@
#pragma once
#include <cstdint>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
#include "app/common/App_structs.h"
class ArchiveFile;
class ArchiveManager {
public:
ArchiveManager();
void loadMediaArchive();
ArchiveFile* getMediaArchive() const { return m_mediaArchive; }
int getArchiveFileSize(const std::wstring& filename);
bool hasArchiveFile(const std::wstring& filename);
std::vector<uint8_t> getArchiveFile(const std::wstring& filename);
// Texture Pack Data files (icon, banner, comparison shot & text)
void addMemoryTPDFile(int iConfig, std::uint8_t* pbData,
unsigned int byteCount);
void removeMemoryTPDFile(int iConfig);
bool isFileInTPD(int iConfig);
void getTPD(int iConfig, std::uint8_t** ppbData, unsigned int* pByteCount);
int getTPDSize() { return m_MEM_TPD.size(); }
int getTPConfigVal(wchar_t* pwchDataFile);
void setRequiredTexturePackID(std::uint32_t texturePackId) {
m_dwRequiredTexturePackID = texturePackId;
}
std::uint32_t getRequiredTexturePackID() const {
return m_dwRequiredTexturePackID;
}
virtual void getFileFromTPD(eTPDFileType eType, std::uint8_t* pbData,
unsigned int byteCount, std::uint8_t** ppbData,
unsigned int* pByteCount) {
*ppbData = nullptr;
*pByteCount = 0;
}
protected:
ArchiveFile* m_mediaArchive;
private:
std::unordered_map<int, PMEMDATA> m_MEM_TPD;
std::mutex csMemTPDLock;
std::uint32_t m_dwRequiredTexturePackID;
};

File diff suppressed because it is too large Load diff

View file

@ -9,11 +9,14 @@
// using namespace std;
#include "app/common/ArchiveManager.h"
#include "app/common/BannedListManager.h"
#include "app/common/DebugOptions.h"
#include "app/common/IPlatformGame.h"
#include "app/common/App_structs.h"
#include "app/common/LocalizationManager.h"
#include "app/common/SaveManager.h"
#include "app/common/SkinManager.h"
#include "app/common/TerrainFeatureManager.h"
#include "app/common/Audio/Consoles_SoundEngine.h"
#include "app/common/DLC/DLCManager.h"
@ -60,9 +63,6 @@ class Merchant;
class CMinecraftAudio;
class Game : public IPlatformGame {
private:
static int s_iHTMLFontSizesA[eHTMLSize_COUNT];
public:
Game();
@ -72,13 +72,16 @@ public:
typedef std::vector<PMEMDATA> VMEMFILES;
typedef std::vector<PNOTIFICATION> VNOTIFICATIONS;
// storing skin files
std::vector<std::wstring> vSkinNames;
// storing skin files - delegated to SkinManager
std::vector<std::wstring>& vSkinNames = m_skinManager.vSkinNames;
DLCManager m_dlcManager;
SaveManager m_saveManager;
BannedListManager m_bannedListManager;
TerrainFeatureManager m_terrainFeatureManager;
DebugOptions m_debugOptions;
LocalizationManager m_localizationManager;
ArchiveManager m_archiveManager;
SkinManager m_skinManager;
// storing credits text from the DLC
std::vector<std::wstring> m_vCreditText; // hold the credit text lines so
@ -198,6 +201,7 @@ public:
void SetSpecialTutorialCompletionFlag(int iPad, int index);
static const wchar_t* GetString(int iID);
StringTable* getStringTable() const { return m_localizationManager.getStringTable(); }
eGameMode GetGameMode() { return m_eGameMode; }
void SetGameMode(eGameMode eMode) { m_eGameMode = eMode; }
@ -303,24 +307,44 @@ public:
void SetGameSettings(int iPad, eGameSetting eVal, unsigned char ucVal);
unsigned char GetGameSettings(int iPad, eGameSetting eVal);
unsigned char GetGameSettings(eGameSetting eVal); // for the primary pad
void SetPlayerSkin(int iPad, const std::wstring& name);
void SetPlayerSkin(int iPad, std::uint32_t dwSkinId);
void SetPlayerCape(int iPad, const std::wstring& name);
void SetPlayerCape(int iPad, std::uint32_t dwCapeId);
void SetPlayerFavoriteSkin(int iPad, int iIndex, unsigned int uiSkinID);
unsigned int GetPlayerFavoriteSkin(int iPad, int iIndex);
unsigned char GetPlayerFavoriteSkinsPos(int iPad);
void SetPlayerFavoriteSkinsPos(int iPad, int iPos);
unsigned int GetPlayerFavoriteSkinsCount(int iPad);
void ValidateFavoriteSkins(
int iPad); // check the DLC is available for the skins
void SetPlayerSkin(int iPad, const std::wstring& name) {
m_skinManager.setPlayerSkin(iPad, name, GameSettingsA);
}
void SetPlayerSkin(int iPad, std::uint32_t dwSkinId) {
m_skinManager.setPlayerSkin(iPad, dwSkinId, GameSettingsA);
}
void SetPlayerCape(int iPad, const std::wstring& name) {
m_skinManager.setPlayerCape(iPad, name, GameSettingsA);
}
void SetPlayerCape(int iPad, std::uint32_t dwCapeId) {
m_skinManager.setPlayerCape(iPad, dwCapeId, GameSettingsA);
}
void SetPlayerFavoriteSkin(int iPad, int iIndex, unsigned int uiSkinID) {
m_skinManager.setPlayerFavoriteSkin(iPad, iIndex, uiSkinID, GameSettingsA);
}
unsigned int GetPlayerFavoriteSkin(int iPad, int iIndex) {
return m_skinManager.getPlayerFavoriteSkin(iPad, iIndex, GameSettingsA);
}
unsigned char GetPlayerFavoriteSkinsPos(int iPad) {
return m_skinManager.getPlayerFavoriteSkinsPos(iPad, GameSettingsA);
}
void SetPlayerFavoriteSkinsPos(int iPad, int iPos) {
m_skinManager.setPlayerFavoriteSkinsPos(iPad, iPos, GameSettingsA);
}
unsigned int GetPlayerFavoriteSkinsCount(int iPad) {
return m_skinManager.getPlayerFavoriteSkinsCount(iPad, GameSettingsA);
}
void ValidateFavoriteSkins(int iPad) {
m_skinManager.validateFavoriteSkins(iPad, GameSettingsA, m_dlcManager);
}
// Mash-up pack worlds hide/display
void HideMashupPackWorld(int iPad, unsigned int iMashupPackID);
void EnableMashupPackWorlds(int iPad);
unsigned int GetMashupPackWorlds(int iPad);
// Minecraft language select
// Minecraft language select - implementations remain in Game.cpp
// (they access GameSettingsA directly)
void SetMinecraftLanguage(int iPad, unsigned char ucLanguage);
unsigned char GetMinecraftLanguage(int iPad);
void SetMinecraftLocale(int iPad, unsigned char ucLanguage);
@ -339,11 +363,21 @@ public:
}
public:
std::wstring GetPlayerSkinName(int iPad);
std::uint32_t GetPlayerSkinId(int iPad);
std::wstring GetPlayerCapeName(int iPad);
std::uint32_t GetPlayerCapeId(int iPad);
std::uint32_t GetAdditionalModelParts(int iPad);
std::wstring GetPlayerSkinName(int iPad) {
return m_skinManager.getPlayerSkinName(iPad, GameSettingsA);
}
std::uint32_t GetPlayerSkinId(int iPad) {
return m_skinManager.getPlayerSkinId(iPad, GameSettingsA, m_dlcManager);
}
std::wstring GetPlayerCapeName(int iPad) {
return m_skinManager.getPlayerCapeName(iPad, GameSettingsA);
}
std::uint32_t GetPlayerCapeId(int iPad) {
return m_skinManager.getPlayerCapeId(iPad, GameSettingsA);
}
std::uint32_t GetAdditionalModelParts(int iPad) {
return m_skinManager.getAdditionalModelParts(iPad);
}
void CheckGameSettingsChanged(bool bOverride5MinuteTimer = false,
int iPad = XUSER_INDEX_ANY);
void ApplyGameSettingsChanged(int iPad);
@ -430,26 +464,48 @@ public:
virtual void StoreLaunchData();
virtual void ExitGame();
bool isXuidNotch(PlayerUID xuid);
bool isXuidNotch(PlayerUID xuid) {
return m_skinManager.isXuidNotch(xuid);
}
bool isXuidDeadmau5(PlayerUID xuid);
void AddMemoryTextureFile(const std::wstring& wName, std::uint8_t* pbData,
unsigned int byteCount);
void RemoveMemoryTextureFile(const std::wstring& wName);
unsigned int byteCount) {
m_skinManager.addMemoryTextureFile(wName, pbData, byteCount);
}
void RemoveMemoryTextureFile(const std::wstring& wName) {
m_skinManager.removeMemoryTextureFile(wName);
}
void GetMemFileDetails(const std::wstring& wName, std::uint8_t** ppbData,
unsigned int* pByteCount);
bool IsFileInMemoryTextures(const std::wstring& wName);
unsigned int* pByteCount) {
m_skinManager.getMemFileDetails(wName, ppbData, pByteCount);
}
bool IsFileInMemoryTextures(const std::wstring& wName) {
return m_skinManager.isFileInMemoryTextures(wName);
}
// Texture Pack Data files (icon, banner, comparison shot & text)
void AddMemoryTPDFile(int iConfig, std::uint8_t* pbData,
unsigned int byteCount);
void RemoveMemoryTPDFile(int iConfig);
bool IsFileInTPD(int iConfig);
void GetTPD(int iConfig, std::uint8_t** ppbData, unsigned int* pByteCount);
int GetTPDSize() { return m_MEM_TPD.size(); }
int GetTPConfigVal(wchar_t* pwchDataFile);
unsigned int byteCount) {
m_archiveManager.addMemoryTPDFile(iConfig, pbData, byteCount);
}
void RemoveMemoryTPDFile(int iConfig) {
m_archiveManager.removeMemoryTPDFile(iConfig);
}
bool IsFileInTPD(int iConfig) {
return m_archiveManager.isFileInTPD(iConfig);
}
void GetTPD(int iConfig, std::uint8_t** ppbData, unsigned int* pByteCount) {
m_archiveManager.getTPD(iConfig, ppbData, pByteCount);
}
int GetTPDSize() { return m_archiveManager.getTPDSize(); }
int GetTPConfigVal(wchar_t* pwchDataFile) {
return m_archiveManager.getTPConfigVal(pwchDataFile);
}
bool DefaultCapeExists();
bool DefaultCapeExists() {
return m_skinManager.defaultCapeExists();
}
// void InstallDefaultCape(); // attempt to install the default cape once
// per game launch
@ -463,16 +519,8 @@ public:
void AddCreditText(const wchar_t* lpStr);
private:
PlayerUID m_xuidNotch;
std::unordered_map<PlayerUID, std::uint8_t*> m_GTS_Files;
// for storing memory textures - player skin
std::unordered_map<std::wstring, PMEMDATA> m_MEM_Files;
// for storing texture pack data files
std::unordered_map<int, PMEMDATA> m_MEM_TPD;
std::mutex csMemFilesLock; // For locking access to the above map
std::mutex csMemTPDLock; // For locking access to the above map
VNOTIFICATIONS m_vNotifications;
public:
@ -519,17 +567,21 @@ public:
// trial, and trying to unlock full
// version on an upsell
void loadMediaArchive();
void loadStringTable();
protected:
ArchiveFile* m_mediaArchive;
StringTable* m_stringTable;
void loadMediaArchive() { m_archiveManager.loadMediaArchive(); }
void loadStringTable() {
m_localizationManager.loadStringTable(m_archiveManager.getMediaArchive());
}
public:
int getArchiveFileSize(const std::wstring& filename);
bool hasArchiveFile(const std::wstring& filename);
std::vector<uint8_t> getArchiveFile(const std::wstring& filename);
int getArchiveFileSize(const std::wstring& filename) {
return m_archiveManager.getArchiveFileSize(filename);
}
bool hasArchiveFile(const std::wstring& filename) {
return m_archiveManager.hasArchiveFile(filename);
}
std::vector<uint8_t> getArchiveFile(const std::wstring& filename) {
return m_archiveManager.getArchiveFile(filename);
}
private:
static int BannedLevelDialogReturned(void* pParam, int iPad,
@ -638,24 +690,29 @@ private:
TimeInfo m_Time;
protected:
static const int MAX_TIPS_GAMETIP = 50;
static const int MAX_TIPS_TRIVIATIP = 20;
static TIPSTRUCT m_GameTipA[MAX_TIPS_GAMETIP];
static TIPSTRUCT m_TriviaTipA[MAX_TIPS_TRIVIATIP];
static Random* TipRandom;
public:
void InitialiseTips();
int GetNextTip();
int GetHTMLColour(eMinecraftColour colour);
void InitialiseTips() { m_localizationManager.initialiseTips(); }
int GetNextTip() { return m_localizationManager.getNextTip(); }
int GetHTMLColour(eMinecraftColour colour) {
return m_localizationManager.getHTMLColour(colour);
}
int GetHTMLColor(eMinecraftColour colour) { return GetHTMLColour(colour); }
int GetHTMLFontSize(EHTMLFontSize size);
int GetHTMLFontSize(EHTMLFontSize size) {
return m_localizationManager.getHTMLFontSize(size);
}
std::wstring FormatHTMLString(int iPad, const std::wstring& desc,
int shadowColour = 0xFFFFFFFF);
std::wstring GetActionReplacement(int iPad, unsigned char ucAction);
std::wstring GetVKReplacement(unsigned int uiVKey);
std::wstring GetIconReplacement(unsigned int uiIcon);
int shadowColour = 0xFFFFFFFF) {
return m_localizationManager.formatHTMLString(iPad, desc, shadowColour);
}
std::wstring GetActionReplacement(int iPad, unsigned char ucAction) {
return m_localizationManager.getActionReplacement(iPad, ucAction);
}
std::wstring GetVKReplacement(unsigned int uiVKey) {
return m_localizationManager.getVKReplacement(uiVKey);
}
std::wstring GetIconReplacement(unsigned int uiIcon) {
return m_localizationManager.getIconReplacement(uiIcon);
}
float getAppTime() { return m_Time.fAppTime; }
void UpdateTrialPausedTimer() { mfTrialPausedTime += m_Time.fElapsedTime; }
@ -665,11 +722,6 @@ public:
static int ExitGameFromRemoteSaveDialogReturned(
void* pParam, int iPad, C4JStorage::EMessageResult result);
private:
int m_TipIDA[MAX_TIPS_GAMETIP + MAX_TIPS_TRIVIATIP];
unsigned int m_uiCurrentTip;
static int TipsSortFunction(const void* a, const void* b);
// XML
public:
// Hold a vector of terrain feature positions
@ -905,13 +957,8 @@ private:
bool m_bTickTMSDLCFiles;
std::mutex csDLCDownloadQueue;
std::mutex csTMSPPDownloadQueue;
std::mutex csAdditionalModelParts;
std::mutex csAdditionalSkinBoxes;
std::mutex csAnimOverrideBitmask;
bool m_bCorruptSaveDeleted;
std::uint32_t m_dwAdditionalModelParts[XUSER_MAX_COUNT];
std::uint8_t*& m_pBannedListFileBuffer = m_bannedListManager.m_pBannedListFileBuffer;
unsigned int& m_dwBannedListFileSize = m_bannedListManager.m_dwBannedListFileSize;
@ -928,17 +975,33 @@ public:
// Storing additional model parts per skin texture
void SetAdditionalSkinBoxes(std::uint32_t dwSkinID, SKIN_BOX* SkinBoxA,
unsigned int dwSkinBoxC);
unsigned int dwSkinBoxC) {
m_skinManager.setAdditionalSkinBoxes(dwSkinID, SkinBoxA, dwSkinBoxC);
}
std::vector<ModelPart*>* SetAdditionalSkinBoxes(
std::uint32_t dwSkinID, std::vector<SKIN_BOX*>* pvSkinBoxA);
std::vector<ModelPart*>* GetAdditionalModelParts(std::uint32_t dwSkinID);
std::vector<SKIN_BOX*>* GetAdditionalSkinBoxes(std::uint32_t dwSkinID);
std::uint32_t dwSkinID, std::vector<SKIN_BOX*>* pvSkinBoxA) {
return m_skinManager.setAdditionalSkinBoxes(dwSkinID, pvSkinBoxA);
}
std::vector<ModelPart*>* GetAdditionalModelParts(std::uint32_t dwSkinID) {
return m_skinManager.getAdditionalModelParts(dwSkinID);
}
std::vector<SKIN_BOX*>* GetAdditionalSkinBoxes(std::uint32_t dwSkinID) {
return m_skinManager.getAdditionalSkinBoxes(dwSkinID);
}
void SetAnimOverrideBitmask(std::uint32_t dwSkinID,
unsigned int uiAnimOverrideBitmask);
unsigned int GetAnimOverrideBitmask(std::uint32_t dwSkinID);
unsigned int uiAnimOverrideBitmask) {
m_skinManager.setAnimOverrideBitmask(dwSkinID, uiAnimOverrideBitmask);
}
unsigned int GetAnimOverrideBitmask(std::uint32_t dwSkinID) {
return m_skinManager.getAnimOverrideBitmask(dwSkinID);
}
static std::uint32_t getSkinIdFromPath(const std::wstring& skin);
static std::wstring getSkinPathFromId(std::uint32_t skinId);
static std::uint32_t getSkinIdFromPath(const std::wstring& skin) {
return SkinManager::getSkinIdFromPath(skin);
}
static std::wstring getSkinPathFromId(std::uint32_t skinId) {
return SkinManager::getSkinPathFromId(skinId);
}
int LoadLocalTMSFile(wchar_t* wchTMSFile) override = 0;
int LoadLocalTMSFile(wchar_t* wchTMSFile,
@ -961,39 +1024,37 @@ public:
void ClearBanList(int iPad) { m_bannedListManager.clearBanList(iPad); }
std::uint32_t GetRequiredTexturePackID() {
return m_dwRequiredTexturePackID;
return m_archiveManager.getRequiredTexturePackID();
}
void SetRequiredTexturePackID(std::uint32_t texturePackId) {
m_dwRequiredTexturePackID = texturePackId;
m_archiveManager.setRequiredTexturePackID(texturePackId);
}
virtual void GetFileFromTPD(eTPDFileType eType, std::uint8_t* pbData,
unsigned int byteCount, std::uint8_t** ppbData,
unsigned int* pByteCount) {
*ppbData = nullptr;
*pByteCount = 0;
m_archiveManager.getFileFromTPD(eType, pbData, byteCount, ppbData,
pByteCount);
}
// XTITLE_DEPLOYMENT_TYPE getDeploymentType() { return
// m_titleDeploymentType; }
private:
// vector of additional skin model parts, indexed by the skin texture id
std::unordered_map<std::uint32_t, std::vector<ModelPart*>*>
m_AdditionalModelParts;
std::unordered_map<std::uint32_t, std::vector<SKIN_BOX*>*>
m_AdditionalSkinBoxes;
std::unordered_map<std::uint32_t, unsigned int> m_AnimOverrides;
bool m_bResetNether;
std::uint32_t m_dwRequiredTexturePackID;
// 4J-PB - language and locale functions
public:
void LocaleAndLanguageInit();
void getLocale(std::vector<std::wstring>& vecWstrLocales);
int get_eMCLang(wchar_t* pwchLocale);
int get_xcLang(wchar_t* pwchLocale);
void LocaleAndLanguageInit() { m_localizationManager.localeAndLanguageInit(); }
void getLocale(std::vector<std::wstring>& vecWstrLocales) {
m_localizationManager.getLocale(vecWstrLocales);
}
int get_eMCLang(wchar_t* pwchLocale) {
return m_localizationManager.get_eMCLang(pwchLocale);
}
int get_xcLang(wchar_t* pwchLocale) {
return m_localizationManager.get_xcLang(pwchLocale);
}
void SetTickTMSDLCFiles(bool bVal);
@ -1002,9 +1063,6 @@ public:
std::wstring mountPoint = L"TPACK:");
private:
std::unordered_map<int, std::wstring> m_localeA;
std::unordered_map<std::wstring, int> m_eMCLangA;
std::unordered_map<std::wstring, int> m_xcLangA;
std::wstring getRootPath(std::uint32_t packId, bool allowOverride,
bool bAddDataFolder, std::wstring mountPoint);

View file

@ -0,0 +1,863 @@
#include "app/common/LocalizationManager.h"
#include <assert.h>
#include <stdlib.h>
#include <wchar.h>
#include <string>
#include "app/common/App_enums.h"
#include "app/common/App_structs.h"
#include "app/common/Localisation/StringTable.h"
#include "app/common/Colours/ColourTable.h"
#include "app/common/UI/All Platforms/ArchiveFile.h"
#include "app/linux/LinuxGame.h"
#include "java/Random.h"
#include "minecraft/client/Minecraft.h"
#include "minecraft/client/skins/TexturePack.h"
#include "minecraft/client/skins/TexturePackRepository.h"
#include "platform/InputActions.h"
#include "platform/sdl2/Input.h"
#include "platform/sdl2/Render.h"
#include "platform/XboxStubs.h"
#include "strings.h"
#include "util/StringHelpers.h"
int LocalizationManager::s_iHTMLFontSizesA[eHTMLSize_COUNT] = {
20, 13, 20, 26};
TIPSTRUCT LocalizationManager::m_GameTipA[MAX_TIPS_GAMETIP] = {
{0, IDS_TIPS_GAMETIP_1}, {0, IDS_TIPS_GAMETIP_2},
{0, IDS_TIPS_GAMETIP_3}, {0, IDS_TIPS_GAMETIP_4},
{0, IDS_TIPS_GAMETIP_5}, {0, IDS_TIPS_GAMETIP_6},
{0, IDS_TIPS_GAMETIP_7}, {0, IDS_TIPS_GAMETIP_8},
{0, IDS_TIPS_GAMETIP_9}, {0, IDS_TIPS_GAMETIP_10},
{0, IDS_TIPS_GAMETIP_11}, {0, IDS_TIPS_GAMETIP_12},
{0, IDS_TIPS_GAMETIP_13}, {0, IDS_TIPS_GAMETIP_14},
{0, IDS_TIPS_GAMETIP_15}, {0, IDS_TIPS_GAMETIP_16},
{0, IDS_TIPS_GAMETIP_17}, {0, IDS_TIPS_GAMETIP_18},
{0, IDS_TIPS_GAMETIP_19}, {0, IDS_TIPS_GAMETIP_20},
{0, IDS_TIPS_GAMETIP_21}, {0, IDS_TIPS_GAMETIP_22},
{0, IDS_TIPS_GAMETIP_23}, {0, IDS_TIPS_GAMETIP_24},
{0, IDS_TIPS_GAMETIP_25}, {0, IDS_TIPS_GAMETIP_26},
{0, IDS_TIPS_GAMETIP_27}, {0, IDS_TIPS_GAMETIP_28},
{0, IDS_TIPS_GAMETIP_29}, {0, IDS_TIPS_GAMETIP_30},
{0, IDS_TIPS_GAMETIP_31}, {0, IDS_TIPS_GAMETIP_32},
{0, IDS_TIPS_GAMETIP_33}, {0, IDS_TIPS_GAMETIP_34},
{0, IDS_TIPS_GAMETIP_35}, {0, IDS_TIPS_GAMETIP_36},
{0, IDS_TIPS_GAMETIP_37}, {0, IDS_TIPS_GAMETIP_38},
{0, IDS_TIPS_GAMETIP_39}, {0, IDS_TIPS_GAMETIP_40},
{0, IDS_TIPS_GAMETIP_41}, {0, IDS_TIPS_GAMETIP_42},
{0, IDS_TIPS_GAMETIP_43}, {0, IDS_TIPS_GAMETIP_44},
{0, IDS_TIPS_GAMETIP_45}, {0, IDS_TIPS_GAMETIP_46},
{0, IDS_TIPS_GAMETIP_47}, {0, IDS_TIPS_GAMETIP_48},
{0, IDS_TIPS_GAMETIP_49}, {0, IDS_TIPS_GAMETIP_50},
};
TIPSTRUCT LocalizationManager::m_TriviaTipA[MAX_TIPS_TRIVIATIP] = {
{0, IDS_TIPS_TRIVIA_1}, {0, IDS_TIPS_TRIVIA_2}, {0, IDS_TIPS_TRIVIA_3},
{0, IDS_TIPS_TRIVIA_4}, {0, IDS_TIPS_TRIVIA_5}, {0, IDS_TIPS_TRIVIA_6},
{0, IDS_TIPS_TRIVIA_7}, {0, IDS_TIPS_TRIVIA_8}, {0, IDS_TIPS_TRIVIA_9},
{0, IDS_TIPS_TRIVIA_10}, {0, IDS_TIPS_TRIVIA_11}, {0, IDS_TIPS_TRIVIA_12},
{0, IDS_TIPS_TRIVIA_13}, {0, IDS_TIPS_TRIVIA_14}, {0, IDS_TIPS_TRIVIA_15},
{0, IDS_TIPS_TRIVIA_16}, {0, IDS_TIPS_TRIVIA_17}, {0, IDS_TIPS_TRIVIA_18},
{0, IDS_TIPS_TRIVIA_19}, {0, IDS_TIPS_TRIVIA_20},
};
Random* LocalizationManager::TipRandom = new Random();
LocalizationManager::LocalizationManager()
: m_stringTable(nullptr), m_uiCurrentTip(0) {
memset(m_TipIDA, 0, sizeof(m_TipIDA));
}
void LocalizationManager::loadStringTable(ArchiveFile* mediaArchive) {
if (m_stringTable != nullptr) {
// we need to unload the current std::string table, this is a reload
delete m_stringTable;
}
std::wstring localisationFile = L"languages.loc";
if (mediaArchive->hasFile(localisationFile)) {
std::vector<uint8_t> locFile =
mediaArchive->getFile(localisationFile);
m_stringTable = new StringTable(locFile.data(), locFile.size());
} else {
m_stringTable = nullptr;
assert(false);
// AHHHHHHHHH.
}
}
const wchar_t* LocalizationManager::getString(int iID) const {
return m_stringTable->getString(iID);
}
int LocalizationManager::TipsSortFunction(const void* a, const void* b) {
int s1 = ((TIPSTRUCT*)a)->iSortValue;
int s2 = ((TIPSTRUCT*)b)->iSortValue;
if (s1 > s2) {
return 1;
} else if (s1 == s2) {
return 0;
}
return -1;
}
void LocalizationManager::initialiseTips() {
memset(m_TipIDA, 0, sizeof(m_TipIDA));
if (!RenderManager.IsHiDef()) {
m_GameTipA[0].uiStringID = IDS_TIPS_GAMETIP_0;
}
#if defined(_CONTENT_PACKAGE)
for (int i = 1; i < MAX_TIPS_GAMETIP; i++) {
m_GameTipA[i].iSortValue = TipRandom->nextInt();
}
qsort(&m_GameTipA[1], MAX_TIPS_GAMETIP - 1, sizeof(TIPSTRUCT),
TipsSortFunction);
#endif
for (int i = 0; i < MAX_TIPS_TRIVIATIP; i++) {
m_TriviaTipA[i].iSortValue = TipRandom->nextInt();
}
qsort(m_TriviaTipA, MAX_TIPS_TRIVIATIP, sizeof(TIPSTRUCT),
TipsSortFunction);
int iCurrentGameTip = 0;
int iCurrentTriviaTip = 0;
for (int i = 0; i < MAX_TIPS_GAMETIP + MAX_TIPS_TRIVIATIP; i++) {
if ((i % 3 == 2) && (iCurrentTriviaTip < MAX_TIPS_TRIVIATIP)) {
m_TipIDA[i] = m_TriviaTipA[iCurrentTriviaTip++].uiStringID;
} else {
if (iCurrentGameTip < MAX_TIPS_GAMETIP) {
m_TipIDA[i] = m_GameTipA[iCurrentGameTip++].uiStringID;
} else {
m_TipIDA[i] = m_TriviaTipA[iCurrentTriviaTip++].uiStringID;
}
}
if (m_TipIDA[i] == 0) {
#if !defined(_CONTENT_PACKAGE)
__debugbreak();
#endif
}
}
m_uiCurrentTip = 0;
}
int LocalizationManager::getNextTip() {
static bool bShowSkinDLCTip = true;
if (app.GetNewDLCAvailable() && app.DisplayNewDLCTip()) {
return IDS_TIPS_GAMETIP_NEWDLC;
} else {
if (bShowSkinDLCTip) {
bShowSkinDLCTip = false;
if (app.DLCInstallProcessCompleted()) {
if (app.m_dlcManager.getPackCount(DLCManager::e_DLCType_Skin) ==
0) {
return IDS_TIPS_GAMETIP_SKINPACKS;
}
} else {
return IDS_TIPS_GAMETIP_SKINPACKS;
}
}
}
if (m_uiCurrentTip == MAX_TIPS_GAMETIP + MAX_TIPS_TRIVIATIP)
m_uiCurrentTip = 0;
return m_TipIDA[m_uiCurrentTip++];
}
int LocalizationManager::getHTMLColour(eMinecraftColour colour) {
Minecraft* pMinecraft = Minecraft::GetInstance();
return pMinecraft->skins->getSelected()->getColourTable()->getColour(
colour);
}
int LocalizationManager::getHTMLFontSize(EHTMLFontSize size) {
return s_iHTMLFontSizesA[size];
}
std::wstring LocalizationManager::formatHTMLString(
int iPad, const std::wstring& desc, int shadowColour /*= 0xFFFFFFFF*/) {
std::wstring text(desc);
wchar_t replacements[64];
text = replaceAll(text, L"{*B*}", L"<br />");
swprintf(replacements, 64, L"<font color=\"#%08x\">",
getHTMLColour(eHTMLColor_T1));
text = replaceAll(text, L"{*T1*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\">",
getHTMLColour(eHTMLColor_T2));
text = replaceAll(text, L"{*T2*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\">",
getHTMLColour(eHTMLColor_T3));
text = replaceAll(text, L"{*T3*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\">",
getHTMLColour(eHTMLColor_Black));
text = replaceAll(text, L"{*ETB*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\">",
getHTMLColour(eHTMLColor_White));
text = replaceAll(text, L"{*ETW*}", replacements);
text = replaceAll(text, L"{*EF*}", L"</font>");
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_0), shadowColour);
text = replaceAll(text, L"{*C0*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_1), shadowColour);
text = replaceAll(text, L"{*C1*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_2), shadowColour);
text = replaceAll(text, L"{*C2*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_3), shadowColour);
text = replaceAll(text, L"{*C3*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_4), shadowColour);
text = replaceAll(text, L"{*C4*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_5), shadowColour);
text = replaceAll(text, L"{*C5*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_6), shadowColour);
text = replaceAll(text, L"{*C6*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_7), shadowColour);
text = replaceAll(text, L"{*C7*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_8), shadowColour);
text = replaceAll(text, L"{*C8*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_9), shadowColour);
text = replaceAll(text, L"{*C9*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_a), shadowColour);
text = replaceAll(text, L"{*CA*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_b), shadowColour);
text = replaceAll(text, L"{*CB*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_c), shadowColour);
text = replaceAll(text, L"{*CC*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_d), shadowColour);
text = replaceAll(text, L"{*CD*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_e), shadowColour);
text = replaceAll(text, L"{*CE*}", replacements);
swprintf(replacements, 64, L"<font color=\"#%08x\" shadowcolor=\"#%08x\">",
getHTMLColour(eHTMLColor_f), shadowColour);
text = replaceAll(text, L"{*CF*}", replacements);
// Swap for southpaw.
if (app.GetGameSettings(iPad, eGameSetting_ControlSouthPaw)) {
text =
replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}",
getActionReplacement(iPad, MINECRAFT_ACTION_LOOK_RIGHT));
text = replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}",
getActionReplacement(iPad, MINECRAFT_ACTION_RIGHT));
text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}",
getVKReplacement(VK_PAD_RTHUMB_LEFT));
} else {
text = replaceAll(text, L"{*CONTROLLER_ACTION_MOVE*}",
getActionReplacement(iPad, MINECRAFT_ACTION_RIGHT));
text =
replaceAll(text, L"{*CONTROLLER_ACTION_LOOK*}",
getActionReplacement(iPad, MINECRAFT_ACTION_LOOK_RIGHT));
text = replaceAll(text, L"{*CONTROLLER_MENU_NAVIGATE*}",
getVKReplacement(VK_PAD_LTHUMB_LEFT));
}
text = replaceAll(text, L"{*CONTROLLER_ACTION_JUMP*}",
getActionReplacement(iPad, MINECRAFT_ACTION_JUMP));
text =
replaceAll(text, L"{*CONTROLLER_ACTION_SNEAK*}",
getActionReplacement(iPad, MINECRAFT_ACTION_SNEAK_TOGGLE));
text = replaceAll(text, L"{*CONTROLLER_ACTION_USE*}",
getActionReplacement(iPad, MINECRAFT_ACTION_USE));
text = replaceAll(text, L"{*CONTROLLER_ACTION_ACTION*}",
getActionReplacement(iPad, MINECRAFT_ACTION_ACTION));
text = replaceAll(text, L"{*CONTROLLER_ACTION_LEFT_SCROLL*}",
getActionReplacement(iPad, MINECRAFT_ACTION_LEFT_SCROLL));
text =
replaceAll(text, L"{*CONTROLLER_ACTION_RIGHT_SCROLL*}",
getActionReplacement(iPad, MINECRAFT_ACTION_RIGHT_SCROLL));
text = replaceAll(text, L"{*CONTROLLER_ACTION_INVENTORY*}",
getActionReplacement(iPad, MINECRAFT_ACTION_INVENTORY));
text = replaceAll(text, L"{*CONTROLLER_ACTION_CRAFTING*}",
getActionReplacement(iPad, MINECRAFT_ACTION_CRAFTING));
text = replaceAll(text, L"{*CONTROLLER_ACTION_DROP*}",
getActionReplacement(iPad, MINECRAFT_ACTION_DROP));
text = replaceAll(
text, L"{*CONTROLLER_ACTION_CAMERA*}",
getActionReplacement(iPad, MINECRAFT_ACTION_RENDER_THIRD_PERSON));
text = replaceAll(text, L"{*CONTROLLER_ACTION_MENU_PAGEDOWN*}",
getActionReplacement(iPad, ACTION_MENU_PAGEDOWN));
text =
replaceAll(text, L"{*CONTROLLER_ACTION_DISMOUNT*}",
getActionReplacement(iPad, MINECRAFT_ACTION_SNEAK_TOGGLE));
text = replaceAll(text, L"{*CONTROLLER_VK_A*}", getVKReplacement(VK_PAD_A));
text = replaceAll(text, L"{*CONTROLLER_VK_B*}", getVKReplacement(VK_PAD_B));
text = replaceAll(text, L"{*CONTROLLER_VK_X*}", getVKReplacement(VK_PAD_X));
text = replaceAll(text, L"{*CONTROLLER_VK_Y*}", getVKReplacement(VK_PAD_Y));
text = replaceAll(text, L"{*CONTROLLER_VK_LB*}",
getVKReplacement(VK_PAD_LSHOULDER));
text = replaceAll(text, L"{*CONTROLLER_VK_RB*}",
getVKReplacement(VK_PAD_RSHOULDER));
text = replaceAll(text, L"{*CONTROLLER_VK_LS*}",
getVKReplacement(VK_PAD_LTHUMB_UP));
text = replaceAll(text, L"{*CONTROLLER_VK_RS*}",
getVKReplacement(VK_PAD_RTHUMB_UP));
text = replaceAll(text, L"{*CONTROLLER_VK_LT*}",
getVKReplacement(VK_PAD_LTRIGGER));
text = replaceAll(text, L"{*CONTROLLER_VK_RT*}",
getVKReplacement(VK_PAD_RTRIGGER));
text = replaceAll(text, L"{*ICON_SHANK_01*}",
getIconReplacement(XZP_ICON_SHANK_01));
text = replaceAll(text, L"{*ICON_SHANK_03*}",
getIconReplacement(XZP_ICON_SHANK_03));
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_UP*}",
getActionReplacement(iPad, MINECRAFT_ACTION_DPAD_UP));
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_DOWN*}",
getActionReplacement(iPad, MINECRAFT_ACTION_DPAD_DOWN));
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_RIGHT*}",
getActionReplacement(iPad, MINECRAFT_ACTION_DPAD_RIGHT));
text = replaceAll(text, L"{*CONTROLLER_ACTION_DPAD_LEFT*}",
getActionReplacement(iPad, MINECRAFT_ACTION_DPAD_LEFT));
std::uint32_t dwLanguage = XGetLanguage();
switch (dwLanguage) {
case XC_LANGUAGE_KOREAN:
case XC_LANGUAGE_JAPANESE:
case XC_LANGUAGE_TCHINESE:
text = replaceAll(text, L"&nbsp;", L"");
break;
}
return text;
}
std::wstring LocalizationManager::getActionReplacement(
int iPad, unsigned char ucAction) {
unsigned int input = InputManager.GetGameJoypadMaps(
InputManager.GetJoypadMapVal(iPad), ucAction);
std::wstring replacement = L"";
if (input & _360_JOY_BUTTON_A)
replacement = L"ButtonA";
else if (input & _360_JOY_BUTTON_B)
replacement = L"ButtonB";
else if (input & _360_JOY_BUTTON_X)
replacement = L"ButtonX";
else if (input & _360_JOY_BUTTON_Y)
replacement = L"ButtonY";
else if ((input & _360_JOY_BUTTON_LSTICK_UP) ||
(input & _360_JOY_BUTTON_LSTICK_DOWN) ||
(input & _360_JOY_BUTTON_LSTICK_LEFT) ||
(input & _360_JOY_BUTTON_LSTICK_RIGHT)) {
replacement = L"ButtonLeftStick";
} else if ((input & _360_JOY_BUTTON_RSTICK_LEFT) ||
(input & _360_JOY_BUTTON_RSTICK_RIGHT) ||
(input & _360_JOY_BUTTON_RSTICK_UP) ||
(input & _360_JOY_BUTTON_RSTICK_DOWN)) {
replacement = L"ButtonRightStick";
} else if (input & _360_JOY_BUTTON_DPAD_LEFT)
replacement = L"ButtonDpadL";
else if (input & _360_JOY_BUTTON_DPAD_RIGHT)
replacement = L"ButtonDpadR";
else if (input & _360_JOY_BUTTON_DPAD_UP)
replacement = L"ButtonDpadU";
else if (input & _360_JOY_BUTTON_DPAD_DOWN)
replacement = L"ButtonDpadD";
else if (input & _360_JOY_BUTTON_LT)
replacement = L"ButtonLeftTrigger";
else if (input & _360_JOY_BUTTON_RT)
replacement = L"ButtonRightTrigger";
else if (input & _360_JOY_BUTTON_RB)
replacement = L"ButtonRightBumper";
else if (input & _360_JOY_BUTTON_LB)
replacement = L"ButtonLeftBumper";
else if (input & _360_JOY_BUTTON_BACK)
replacement = L"ButtonBack";
else if (input & _360_JOY_BUTTON_START)
replacement = L"ButtonStart";
else if (input & _360_JOY_BUTTON_RTHUMB)
replacement = L"ButtonRS";
else if (input & _360_JOY_BUTTON_LTHUMB)
replacement = L"ButtonLS";
wchar_t string[128];
#if defined(_WIN64)
int size = 45;
if (ui.getScreenWidth() < 1920) size = 30;
#else
int size = 45;
#endif
swprintf(string, 128,
L"<img src=\"%ls\" align=\"middle\" height=\"%d\" width=\"%d\"/>",
replacement.c_str(), size, size);
return string;
}
std::wstring LocalizationManager::getVKReplacement(unsigned int uiVKey) {
std::wstring replacement = L"";
switch (uiVKey) {
case VK_PAD_A:
replacement = L"ButtonA";
break;
case VK_PAD_B:
replacement = L"ButtonB";
break;
case VK_PAD_X:
replacement = L"ButtonX";
break;
case VK_PAD_Y:
replacement = L"ButtonY";
break;
case VK_PAD_LSHOULDER:
replacement = L"ButtonLeftBumper";
break;
case VK_PAD_RSHOULDER:
replacement = L"ButtonRightBumper";
break;
case VK_PAD_LTRIGGER:
replacement = L"ButtonLeftTrigger";
break;
case VK_PAD_RTRIGGER:
replacement = L"ButtonRightTrigger";
break;
case VK_PAD_LTHUMB_UP:
case VK_PAD_LTHUMB_DOWN:
case VK_PAD_LTHUMB_RIGHT:
case VK_PAD_LTHUMB_LEFT:
case VK_PAD_LTHUMB_UPLEFT:
case VK_PAD_LTHUMB_UPRIGHT:
case VK_PAD_LTHUMB_DOWNRIGHT:
case VK_PAD_LTHUMB_DOWNLEFT:
replacement = L"ButtonLeftStick";
break;
case VK_PAD_RTHUMB_UP:
case VK_PAD_RTHUMB_DOWN:
case VK_PAD_RTHUMB_RIGHT:
case VK_PAD_RTHUMB_LEFT:
case VK_PAD_RTHUMB_UPLEFT:
case VK_PAD_RTHUMB_UPRIGHT:
case VK_PAD_RTHUMB_DOWNRIGHT:
case VK_PAD_RTHUMB_DOWNLEFT:
replacement = L"ButtonRightStick";
break;
default:
break;
}
wchar_t string[128];
#if defined(_WIN64)
int size = 45;
if (ui.getScreenWidth() < 1920) size = 30;
#else
int size = 45;
#endif
swprintf(string, 128,
L"<img src=\"%ls\" align=\"middle\" height=\"%d\" width=\"%d\"/>",
replacement.c_str(), size, size);
return string;
}
std::wstring LocalizationManager::getIconReplacement(unsigned int uiIcon) {
wchar_t string[128];
#if defined(_WIN64)
int size = 33;
if (ui.getScreenWidth() < 1920) size = 22;
#else
int size = 33;
#endif
swprintf(string, 128,
L"<img src=\"Icon_Shank\" align=\"middle\" height=\"%d\" "
L"width=\"%d\"/>",
size, size);
std::wstring result = L"";
switch (uiIcon) {
case XZP_ICON_SHANK_01:
result = string;
break;
case XZP_ICON_SHANK_03:
result.append(string).append(string).append(string);
break;
default:
break;
}
return result;
}
void LocalizationManager::getLocale(
std::vector<std::wstring>& vecWstrLocales) {
std::vector<eMCLang> locales;
const unsigned int systemLanguage = XGetLanguage();
switch (systemLanguage) {
case XC_LANGUAGE_ENGLISH:
switch (XGetLocale()) {
case XC_LOCALE_AUSTRALIA:
case XC_LOCALE_CANADA:
case XC_LOCALE_CZECH_REPUBLIC:
case XC_LOCALE_GREECE:
case XC_LOCALE_HONG_KONG:
case XC_LOCALE_HUNGARY:
case XC_LOCALE_INDIA:
case XC_LOCALE_IRELAND:
case XC_LOCALE_ISRAEL:
case XC_LOCALE_NEW_ZEALAND:
case XC_LOCALE_SAUDI_ARABIA:
case XC_LOCALE_SINGAPORE:
case XC_LOCALE_SLOVAK_REPUBLIC:
case XC_LOCALE_SOUTH_AFRICA:
case XC_LOCALE_UNITED_ARAB_EMIRATES:
case XC_LOCALE_GREAT_BRITAIN:
locales.push_back(eMCLang_enGB);
break;
default:
break;
}
break;
case XC_LANGUAGE_JAPANESE:
locales.push_back(eMCLang_jaJP);
break;
case XC_LANGUAGE_GERMAN:
switch (XGetLocale()) {
case XC_LOCALE_AUSTRIA:
locales.push_back(eMCLang_deAT);
break;
case XC_LOCALE_SWITZERLAND:
locales.push_back(eMCLang_deCH);
break;
default:
break;
}
locales.push_back(eMCLang_deDE);
break;
case XC_LANGUAGE_FRENCH:
switch (XGetLocale()) {
case XC_LOCALE_BELGIUM:
locales.push_back(eMCLang_frBE);
break;
case XC_LOCALE_CANADA:
locales.push_back(eMCLang_frCA);
break;
case XC_LOCALE_SWITZERLAND:
locales.push_back(eMCLang_frCH);
break;
default:
break;
}
locales.push_back(eMCLang_frFR);
break;
case XC_LANGUAGE_SPANISH:
switch (XGetLocale()) {
case XC_LOCALE_MEXICO:
case XC_LOCALE_ARGENTINA:
case XC_LOCALE_CHILE:
case XC_LOCALE_COLOMBIA:
case XC_LOCALE_UNITED_STATES:
case XC_LOCALE_LATIN_AMERICA:
locales.push_back(eMCLang_laLAS);
locales.push_back(eMCLang_esMX);
break;
default:
break;
}
locales.push_back(eMCLang_esES);
break;
case XC_LANGUAGE_ITALIAN:
locales.push_back(eMCLang_itIT);
break;
case XC_LANGUAGE_KOREAN:
locales.push_back(eMCLang_koKR);
break;
case XC_LANGUAGE_TCHINESE:
switch (XGetLocale()) {
case XC_LOCALE_HONG_KONG:
locales.push_back(eMCLang_zhHK);
locales.push_back(eMCLang_zhTW);
break;
case XC_LOCALE_TAIWAN:
locales.push_back(eMCLang_zhTW);
locales.push_back(eMCLang_zhHK);
default:
break;
}
locales.push_back(eMCLang_hant);
locales.push_back(eMCLang_zhCHT);
break;
case XC_LANGUAGE_PORTUGUESE:
if (XGetLocale() == XC_LOCALE_BRAZIL) {
locales.push_back(eMCLang_ptBR);
}
locales.push_back(eMCLang_ptPT);
break;
case XC_LANGUAGE_POLISH:
locales.push_back(eMCLang_plPL);
break;
case XC_LANGUAGE_RUSSIAN:
locales.push_back(eMCLang_ruRU);
break;
case XC_LANGUAGE_SWEDISH:
locales.push_back(eMCLang_svSV);
locales.push_back(eMCLang_svSE);
break;
case XC_LANGUAGE_TURKISH:
locales.push_back(eMCLang_trTR);
break;
case XC_LANGUAGE_BNORWEGIAN:
locales.push_back(eMCLang_nbNO);
locales.push_back(eMCLang_noNO);
locales.push_back(eMCLang_nnNO);
break;
case XC_LANGUAGE_DUTCH:
switch (XGetLocale()) {
case XC_LOCALE_BELGIUM:
locales.push_back(eMCLang_nlBE);
break;
default:
break;
}
locales.push_back(eMCLang_nlNL);
break;
case XC_LANGUAGE_SCHINESE:
switch (XGetLocale()) {
case XC_LOCALE_SINGAPORE:
locales.push_back(eMCLang_zhSG);
break;
default:
break;
}
locales.push_back(eMCLang_hans);
locales.push_back(eMCLang_csCS);
locales.push_back(eMCLang_zhCN);
break;
}
locales.push_back(eMCLang_enUS);
locales.push_back(eMCLang_null);
for (int i = 0; i < locales.size(); i++) {
eMCLang lang = locales.at(i);
vecWstrLocales.push_back(m_localeA[lang]);
}
}
int LocalizationManager::get_eMCLang(wchar_t* pwchLocale) {
return m_eMCLangA[pwchLocale];
}
int LocalizationManager::get_xcLang(wchar_t* pwchLocale) {
return m_xcLangA[pwchLocale];
}
void LocalizationManager::localeAndLanguageInit() {
m_localeA[eMCLang_zhCHT] = L"zh-CHT";
m_localeA[eMCLang_csCS] = L"cs-CS";
m_localeA[eMCLang_laLAS] = L"la-LAS";
m_localeA[eMCLang_null] = L"en-EN";
m_localeA[eMCLang_enUS] = L"en-US";
m_localeA[eMCLang_enGB] = L"en-GB";
m_localeA[eMCLang_enIE] = L"en-IE";
m_localeA[eMCLang_enAU] = L"en-AU";
m_localeA[eMCLang_enNZ] = L"en-NZ";
m_localeA[eMCLang_enCA] = L"en-CA";
m_localeA[eMCLang_jaJP] = L"ja-JP";
m_localeA[eMCLang_deDE] = L"de-DE";
m_localeA[eMCLang_deAT] = L"de-AT";
m_localeA[eMCLang_frFR] = L"fr-FR";
m_localeA[eMCLang_frCA] = L"fr-CA";
m_localeA[eMCLang_esES] = L"es-ES";
m_localeA[eMCLang_esMX] = L"es-MX";
m_localeA[eMCLang_itIT] = L"it-IT";
m_localeA[eMCLang_koKR] = L"ko-KR";
m_localeA[eMCLang_ptPT] = L"pt-PT";
m_localeA[eMCLang_ptBR] = L"pt-BR";
m_localeA[eMCLang_ruRU] = L"ru-RU";
m_localeA[eMCLang_nlNL] = L"nl-NL";
m_localeA[eMCLang_fiFI] = L"fi-FI";
m_localeA[eMCLang_svSV] = L"sv-SV";
m_localeA[eMCLang_daDA] = L"da-DA";
m_localeA[eMCLang_noNO] = L"no-NO";
m_localeA[eMCLang_plPL] = L"pl-PL";
m_localeA[eMCLang_trTR] = L"tr-TR";
m_localeA[eMCLang_elEL] = L"el-EL";
m_localeA[eMCLang_zhSG] = L"zh-SG";
m_localeA[eMCLang_zhCN] = L"zh-CN";
m_localeA[eMCLang_zhHK] = L"zh-HK";
m_localeA[eMCLang_zhTW] = L"zh-TW";
m_localeA[eMCLang_nlBE] = L"nl-BE";
m_localeA[eMCLang_daDK] = L"da-DK";
m_localeA[eMCLang_frBE] = L"fr-BE";
m_localeA[eMCLang_frCH] = L"fr-CH";
m_localeA[eMCLang_deCH] = L"de-CH";
m_localeA[eMCLang_nbNO] = L"nb-NO";
m_localeA[eMCLang_enGR] = L"en-GR";
m_localeA[eMCLang_enHK] = L"en-HK";
m_localeA[eMCLang_enSA] = L"en-SA";
m_localeA[eMCLang_enHU] = L"en-HU";
m_localeA[eMCLang_enIN] = L"en-IN";
m_localeA[eMCLang_enIL] = L"en-IL";
m_localeA[eMCLang_enSG] = L"en-SG";
m_localeA[eMCLang_enSK] = L"en-SK";
m_localeA[eMCLang_enZA] = L"en-ZA";
m_localeA[eMCLang_enCZ] = L"en-CZ";
m_localeA[eMCLang_enAE] = L"en-AE";
m_localeA[eMCLang_esAR] = L"es-AR";
m_localeA[eMCLang_esCL] = L"es-CL";
m_localeA[eMCLang_esCO] = L"es-CO";
m_localeA[eMCLang_esUS] = L"es-US";
m_localeA[eMCLang_svSE] = L"sv-SE";
m_localeA[eMCLang_csCZ] = L"cs-CZ";
m_localeA[eMCLang_elGR] = L"el-GR";
m_localeA[eMCLang_nnNO] = L"nn-NO";
m_localeA[eMCLang_skSK] = L"sk-SK";
m_localeA[eMCLang_hans] = L"zh-HANS";
m_localeA[eMCLang_hant] = L"zh-HANT";
m_eMCLangA[L"zh-CHT"] = eMCLang_zhCHT;
m_eMCLangA[L"cs-CS"] = eMCLang_csCS;
m_eMCLangA[L"la-LAS"] = eMCLang_laLAS;
m_eMCLangA[L"en-EN"] = eMCLang_null;
m_eMCLangA[L"en-US"] = eMCLang_enUS;
m_eMCLangA[L"en-GB"] = eMCLang_enGB;
m_eMCLangA[L"en-IE"] = eMCLang_enIE;
m_eMCLangA[L"en-AU"] = eMCLang_enAU;
m_eMCLangA[L"en-NZ"] = eMCLang_enNZ;
m_eMCLangA[L"en-CA"] = eMCLang_enCA;
m_eMCLangA[L"ja-JP"] = eMCLang_jaJP;
m_eMCLangA[L"de-DE"] = eMCLang_deDE;
m_eMCLangA[L"de-AT"] = eMCLang_deAT;
m_eMCLangA[L"fr-FR"] = eMCLang_frFR;
m_eMCLangA[L"fr-CA"] = eMCLang_frCA;
m_eMCLangA[L"es-ES"] = eMCLang_esES;
m_eMCLangA[L"es-MX"] = eMCLang_esMX;
m_eMCLangA[L"it-IT"] = eMCLang_itIT;
m_eMCLangA[L"ko-KR"] = eMCLang_koKR;
m_eMCLangA[L"pt-PT"] = eMCLang_ptPT;
m_eMCLangA[L"pt-BR"] = eMCLang_ptBR;
m_eMCLangA[L"ru-RU"] = eMCLang_ruRU;
m_eMCLangA[L"nl-NL"] = eMCLang_nlNL;
m_eMCLangA[L"fi-FI"] = eMCLang_fiFI;
m_eMCLangA[L"sv-SV"] = eMCLang_svSV;
m_eMCLangA[L"da-DA"] = eMCLang_daDA;
m_eMCLangA[L"no-NO"] = eMCLang_noNO;
m_eMCLangA[L"pl-PL"] = eMCLang_plPL;
m_eMCLangA[L"tr-TR"] = eMCLang_trTR;
m_eMCLangA[L"el-EL"] = eMCLang_elEL;
m_eMCLangA[L"zh-SG"] = eMCLang_zhSG;
m_eMCLangA[L"zh-CN"] = eMCLang_zhCN;
m_eMCLangA[L"zh-HK"] = eMCLang_zhHK;
m_eMCLangA[L"zh-TW"] = eMCLang_zhTW;
m_eMCLangA[L"nl-BE"] = eMCLang_nlBE;
m_eMCLangA[L"da-DK"] = eMCLang_daDK;
m_eMCLangA[L"fr-BE"] = eMCLang_frBE;
m_eMCLangA[L"fr-CH"] = eMCLang_frCH;
m_eMCLangA[L"de-CH"] = eMCLang_deCH;
m_eMCLangA[L"nb-NO"] = eMCLang_nbNO;
m_eMCLangA[L"en-GR"] = eMCLang_enGR;
m_eMCLangA[L"en-HK"] = eMCLang_enHK;
m_eMCLangA[L"en-SA"] = eMCLang_enSA;
m_eMCLangA[L"en-HU"] = eMCLang_enHU;
m_eMCLangA[L"en-IN"] = eMCLang_enIN;
m_eMCLangA[L"en-IL"] = eMCLang_enIL;
m_eMCLangA[L"en-SG"] = eMCLang_enSG;
m_eMCLangA[L"en-SK"] = eMCLang_enSK;
m_eMCLangA[L"en-ZA"] = eMCLang_enZA;
m_eMCLangA[L"en-CZ"] = eMCLang_enCZ;
m_eMCLangA[L"en-AE"] = eMCLang_enAE;
m_eMCLangA[L"es-AR"] = eMCLang_esAR;
m_eMCLangA[L"es-CL"] = eMCLang_esCL;
m_eMCLangA[L"es-CO"] = eMCLang_esCO;
m_eMCLangA[L"es-US"] = eMCLang_esUS;
m_eMCLangA[L"sv-SE"] = eMCLang_svSE;
m_eMCLangA[L"cs-CZ"] = eMCLang_csCZ;
m_eMCLangA[L"el-GR"] = eMCLang_elGR;
m_eMCLangA[L"nn-NO"] = eMCLang_nnNO;
m_eMCLangA[L"sk-SK"] = eMCLang_skSK;
m_eMCLangA[L"zh-HANS"] = eMCLang_hans;
m_eMCLangA[L"zh-HANT"] = eMCLang_hant;
m_xcLangA[L"zh-CHT"] = XC_LOCALE_CHINA;
m_xcLangA[L"cs-CS"] = XC_LOCALE_CHINA;
m_xcLangA[L"en-EN"] = XC_LOCALE_UNITED_STATES;
m_xcLangA[L"en-US"] = XC_LOCALE_UNITED_STATES;
m_xcLangA[L"en-GB"] = XC_LOCALE_GREAT_BRITAIN;
m_xcLangA[L"en-IE"] = XC_LOCALE_IRELAND;
m_xcLangA[L"en-AU"] = XC_LOCALE_AUSTRALIA;
m_xcLangA[L"en-NZ"] = XC_LOCALE_NEW_ZEALAND;
m_xcLangA[L"en-CA"] = XC_LOCALE_CANADA;
m_xcLangA[L"ja-JP"] = XC_LOCALE_JAPAN;
m_xcLangA[L"de-DE"] = XC_LOCALE_GERMANY;
m_xcLangA[L"de-AT"] = XC_LOCALE_AUSTRIA;
m_xcLangA[L"fr-FR"] = XC_LOCALE_FRANCE;
m_xcLangA[L"fr-CA"] = XC_LOCALE_CANADA;
m_xcLangA[L"es-ES"] = XC_LOCALE_SPAIN;
m_xcLangA[L"es-MX"] = XC_LOCALE_MEXICO;
m_xcLangA[L"it-IT"] = XC_LOCALE_ITALY;
m_xcLangA[L"ko-KR"] = XC_LOCALE_KOREA;
m_xcLangA[L"pt-PT"] = XC_LOCALE_PORTUGAL;
m_xcLangA[L"pt-BR"] = XC_LOCALE_BRAZIL;
m_xcLangA[L"ru-RU"] = XC_LOCALE_RUSSIAN_FEDERATION;
m_xcLangA[L"nl-NL"] = XC_LOCALE_NETHERLANDS;
m_xcLangA[L"fi-FI"] = XC_LOCALE_FINLAND;
m_xcLangA[L"sv-SV"] = XC_LOCALE_SWEDEN;
m_xcLangA[L"da-DA"] = XC_LOCALE_DENMARK;
m_xcLangA[L"no-NO"] = XC_LOCALE_NORWAY;
m_xcLangA[L"pl-PL"] = XC_LOCALE_POLAND;
m_xcLangA[L"tr-TR"] = XC_LOCALE_TURKEY;
m_xcLangA[L"el-EL"] = XC_LOCALE_GREECE;
m_xcLangA[L"la-LAS"] = XC_LOCALE_LATIN_AMERICA;
m_xcLangA[L"zh-SG"] = XC_LOCALE_SINGAPORE;
m_xcLangA[L"Zh-CN"] = XC_LOCALE_CHINA;
m_xcLangA[L"zh-HK"] = XC_LOCALE_HONG_KONG;
m_xcLangA[L"zh-TW"] = XC_LOCALE_TAIWAN;
m_xcLangA[L"nl-BE"] = XC_LOCALE_BELGIUM;
m_xcLangA[L"da-DK"] = XC_LOCALE_DENMARK;
m_xcLangA[L"fr-BE"] = XC_LOCALE_BELGIUM;
m_xcLangA[L"fr-CH"] = XC_LOCALE_SWITZERLAND;
m_xcLangA[L"de-CH"] = XC_LOCALE_SWITZERLAND;
m_xcLangA[L"nb-NO"] = XC_LOCALE_NORWAY;
m_xcLangA[L"en-GR"] = XC_LOCALE_GREECE;
m_xcLangA[L"en-HK"] = XC_LOCALE_HONG_KONG;
m_xcLangA[L"en-SA"] = XC_LOCALE_SAUDI_ARABIA;
m_xcLangA[L"en-HU"] = XC_LOCALE_HUNGARY;
m_xcLangA[L"en-IN"] = XC_LOCALE_INDIA;
m_xcLangA[L"en-IL"] = XC_LOCALE_ISRAEL;
m_xcLangA[L"en-SG"] = XC_LOCALE_SINGAPORE;
m_xcLangA[L"en-SK"] = XC_LOCALE_SLOVAK_REPUBLIC;
m_xcLangA[L"en-ZA"] = XC_LOCALE_SOUTH_AFRICA;
m_xcLangA[L"en-CZ"] = XC_LOCALE_CZECH_REPUBLIC;
m_xcLangA[L"en-AE"] = XC_LOCALE_UNITED_ARAB_EMIRATES;
m_xcLangA[L"ja-IP"] = XC_LOCALE_JAPAN;
m_xcLangA[L"es-AR"] = XC_LOCALE_ARGENTINA;
m_xcLangA[L"es-CL"] = XC_LOCALE_CHILE;
m_xcLangA[L"es-CO"] = XC_LOCALE_COLOMBIA;
m_xcLangA[L"es-US"] = XC_LOCALE_UNITED_STATES;
m_xcLangA[L"sv-SE"] = XC_LOCALE_SWEDEN;
m_xcLangA[L"cs-CZ"] = XC_LOCALE_CZECH_REPUBLIC;
m_xcLangA[L"el-GR"] = XC_LOCALE_GREECE;
m_xcLangA[L"sk-SK"] = XC_LOCALE_SLOVAK_REPUBLIC;
m_xcLangA[L"zh-HANS"] = XC_LOCALE_CHINA;
m_xcLangA[L"zh-HANT"] = XC_LOCALE_CHINA;
}

View file

@ -0,0 +1,61 @@
#pragma once
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
#include "app/common/App_enums.h"
#include "app/common/App_structs.h"
#include "platform/XboxStubs.h"
class ArchiveFile;
class Random;
class StringTable;
class LocalizationManager {
public:
LocalizationManager();
void localeAndLanguageInit();
void loadStringTable(ArchiveFile* mediaArchive);
const wchar_t* getString(int iID) const;
std::wstring formatHTMLString(int iPad, const std::wstring& desc,
int shadowColour = 0xFFFFFFFF);
std::wstring getActionReplacement(int iPad, unsigned char ucAction);
std::wstring getVKReplacement(unsigned int uiVKey);
std::wstring getIconReplacement(unsigned int uiIcon);
int getHTMLColour(eMinecraftColour colour);
int getHTMLColor(eMinecraftColour colour) { return getHTMLColour(colour); }
int getHTMLFontSize(EHTMLFontSize size);
void initialiseTips();
int getNextTip();
void getLocale(std::vector<std::wstring>& vecWstrLocales);
int get_eMCLang(wchar_t* pwchLocale);
int get_xcLang(wchar_t* pwchLocale);
StringTable* getStringTable() const { return m_stringTable; }
private:
static int s_iHTMLFontSizesA[eHTMLSize_COUNT];
StringTable* m_stringTable;
std::unordered_map<int, std::wstring> m_localeA;
std::unordered_map<std::wstring, int> m_eMCLangA;
std::unordered_map<std::wstring, int> m_xcLangA;
static const int MAX_TIPS_GAMETIP = 50;
static const int MAX_TIPS_TRIVIATIP = 20;
static TIPSTRUCT m_GameTipA[MAX_TIPS_GAMETIP];
static TIPSTRUCT m_TriviaTipA[MAX_TIPS_TRIVIATIP];
static Random* TipRandom;
int m_TipIDA[MAX_TIPS_GAMETIP + MAX_TIPS_TRIVIATIP];
unsigned int m_uiCurrentTip;
static int TipsSortFunction(const void* a, const void* b);
};

View file

@ -0,0 +1,451 @@
#include "app/common/SkinManager.h"
#include <mutex>
#include <sstream>
#include <string>
#include <wchar.h>
#include "app/common/App_structs.h"
#include "app/common/DLC/DLCManager.h"
#include "app/common/DLC/DLCPack.h"
#include "app/common/DLC/DLCSkinFile.h"
#include "app/common/Minecraft_Macros.h"
#include "app/linux/LinuxGame.h"
#include "minecraft/client/Minecraft.h"
#include "minecraft/client/model/geom/Model.h"
#include "minecraft/client/multiplayer/MultiPlayerLocalPlayer.h"
#include "minecraft/client/renderer/entity/EntityRenderer.h"
#include "minecraft/client/renderer/entity/EntityRenderDispatcher.h"
#include "minecraft/world/entity/player/Player.h"
#include "platform/sdl2/Profile.h"
SkinManager::SkinManager() : m_xuidNotch(INVALID_XUID) {
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
m_dwAdditionalModelParts[i] = 0;
}
}
void SkinManager::setPlayerSkin(int iPad, const std::wstring& name,
GAME_SETTINGS** gameSettingsA) {
std::uint32_t skinId = getSkinIdFromPath(name);
setPlayerSkin(iPad, skinId, gameSettingsA);
}
void SkinManager::setPlayerSkin(int iPad, std::uint32_t dwSkinId,
GAME_SETTINGS** gameSettingsA) {
app.DebugPrintf("Setting skin for %d to %08X\n", iPad, dwSkinId);
gameSettingsA[iPad]->dwSelectedSkin = dwSkinId;
gameSettingsA[iPad]->bSettingsChanged = true;
if (Minecraft::GetInstance()->localplayers[iPad] != nullptr)
Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomSkin(
dwSkinId);
}
std::wstring SkinManager::getPlayerSkinName(int iPad,
GAME_SETTINGS** gameSettingsA) {
return getSkinPathFromId(gameSettingsA[iPad]->dwSelectedSkin);
}
std::uint32_t SkinManager::getPlayerSkinId(int iPad,
GAME_SETTINGS** gameSettingsA,
DLCManager& dlcManager) {
DLCPack* Pack = nullptr;
DLCSkinFile* skinFile = nullptr;
std::uint32_t dwSkin = gameSettingsA[iPad]->dwSelectedSkin;
wchar_t chars[256];
if (GET_IS_DLC_SKIN_FROM_BITMASK(dwSkin)) {
swprintf(chars, 256, L"dlcskin%08d.png",
GET_DLC_SKIN_ID_FROM_BITMASK(dwSkin));
Pack = dlcManager.getPackContainingSkin(chars);
if (Pack) {
skinFile = Pack->getSkinFile(chars);
bool bSkinIsFree =
skinFile->getParameterAsBool(DLCManager::e_DLCParamType_Free);
bool bLicensed = Pack->hasPurchasedFile(DLCManager::e_DLCType_Skin,
skinFile->getPath());
if (bSkinIsFree || bLicensed) {
return dwSkin;
} else {
return 0;
}
}
}
return dwSkin;
}
std::uint32_t SkinManager::getAdditionalModelParts(int iPad) {
return m_dwAdditionalModelParts[iPad];
}
void SkinManager::setPlayerCape(int iPad, const std::wstring& name,
GAME_SETTINGS** gameSettingsA) {
std::uint32_t capeId = Player::getCapeIdFromPath(name);
setPlayerCape(iPad, capeId, gameSettingsA);
}
void SkinManager::setPlayerCape(int iPad, std::uint32_t dwCapeId,
GAME_SETTINGS** gameSettingsA) {
app.DebugPrintf("Setting cape for %d to %08X\n", iPad, dwCapeId);
gameSettingsA[iPad]->dwSelectedCape = dwCapeId;
gameSettingsA[iPad]->bSettingsChanged = true;
if (Minecraft::GetInstance()->localplayers[iPad] != nullptr)
Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomCape(
dwCapeId);
}
std::wstring SkinManager::getPlayerCapeName(int iPad,
GAME_SETTINGS** gameSettingsA) {
return Player::getCapePathFromId(gameSettingsA[iPad]->dwSelectedCape);
}
std::uint32_t SkinManager::getPlayerCapeId(int iPad,
GAME_SETTINGS** gameSettingsA) {
return gameSettingsA[iPad]->dwSelectedCape;
}
void SkinManager::setPlayerFavoriteSkin(int iPad, int iIndex,
unsigned int uiSkinID,
GAME_SETTINGS** gameSettingsA) {
app.DebugPrintf("Setting favorite skin for %d to %08X\n", iPad, uiSkinID);
gameSettingsA[iPad]->uiFavoriteSkinA[iIndex] = uiSkinID;
gameSettingsA[iPad]->bSettingsChanged = true;
}
unsigned int SkinManager::getPlayerFavoriteSkin(
int iPad, int iIndex, GAME_SETTINGS** gameSettingsA) {
return gameSettingsA[iPad]->uiFavoriteSkinA[iIndex];
}
unsigned char SkinManager::getPlayerFavoriteSkinsPos(
int iPad, GAME_SETTINGS** gameSettingsA) {
return gameSettingsA[iPad]->ucCurrentFavoriteSkinPos;
}
void SkinManager::setPlayerFavoriteSkinsPos(int iPad, int iPos,
GAME_SETTINGS** gameSettingsA) {
gameSettingsA[iPad]->ucCurrentFavoriteSkinPos = (unsigned char)iPos;
gameSettingsA[iPad]->bSettingsChanged = true;
}
unsigned int SkinManager::getPlayerFavoriteSkinsCount(
int iPad, GAME_SETTINGS** gameSettingsA) {
unsigned int uiCount = 0;
for (int i = 0; i < MAX_FAVORITE_SKINS; i++) {
if (gameSettingsA[iPad]->uiFavoriteSkinA[i] != 0xFFFFFFFF) {
uiCount++;
} else {
break;
}
}
return uiCount;
}
void SkinManager::validateFavoriteSkins(int iPad,
GAME_SETTINGS** gameSettingsA,
DLCManager& dlcManager) {
unsigned int uiCount = getPlayerFavoriteSkinsCount(iPad, gameSettingsA);
unsigned int uiValidSkin = 0;
wchar_t chars[256];
for (unsigned int i = 0; i < uiCount; i++) {
swprintf(chars, 256, L"dlcskin%08d.png",
getPlayerFavoriteSkin(iPad, i, gameSettingsA));
DLCPack* pDLCPack = dlcManager.getPackContainingSkin(chars);
if (pDLCPack != nullptr) {
DLCSkinFile* pSkinFile = pDLCPack->getSkinFile(chars);
if (pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Skin, L"") ||
(pSkinFile && pSkinFile->isFree())) {
gameSettingsA[iPad]->uiFavoriteSkinA[uiValidSkin++] =
gameSettingsA[iPad]->uiFavoriteSkinA[i];
}
}
}
for (unsigned int i = uiValidSkin; i < MAX_FAVORITE_SKINS; i++) {
gameSettingsA[iPad]->uiFavoriteSkinA[i] = 0xFFFFFFFF;
}
}
bool SkinManager::isXuidNotch(PlayerUID xuid) {
if (m_xuidNotch != INVALID_XUID && xuid != INVALID_XUID) {
return ProfileManager.AreXUIDSEqual(xuid, m_xuidNotch);
}
return false;
}
bool SkinManager::isXuidDeadmau5(PlayerUID xuid) {
// Delegates back to static MojangData on Game - this is a simple forwarding
// wrapper for now; the actual MojangData map stays on Game.
return app.isXuidDeadmau5(xuid);
}
void SkinManager::addMemoryTextureFile(const std::wstring& wName,
std::uint8_t* pbData,
unsigned int byteCount) {
std::lock_guard<std::mutex> lock(csMemFilesLock);
PMEMDATA pData = nullptr;
auto it = m_MEM_Files.find(wName);
if (it != m_MEM_Files.end()) {
#if !defined(_CONTENT_PACKAGE)
wprintf(L"Incrementing the memory texture file count for %ls\n",
wName.c_str());
#endif
pData = (*it).second;
if (pData->byteCount == 0 && byteCount != 0) {
if (pData->pbData != nullptr) delete[] pData->pbData;
pData->pbData = pbData;
pData->byteCount = byteCount;
}
++pData->ucRefCount;
return;
}
pData = new MEMDATA();
pData->pbData = pbData;
pData->byteCount = byteCount;
pData->ucRefCount = 1;
m_MEM_Files[wName] = pData;
}
void SkinManager::removeMemoryTextureFile(const std::wstring& wName) {
std::lock_guard<std::mutex> lock(csMemFilesLock);
auto it = m_MEM_Files.find(wName);
if (it != m_MEM_Files.end()) {
#if !defined(_CONTENT_PACKAGE)
wprintf(L"Decrementing the memory texture file count for %ls\n",
wName.c_str());
#endif
PMEMDATA pData = (*it).second;
--pData->ucRefCount;
if (pData->ucRefCount <= 0) {
#if !defined(_CONTENT_PACKAGE)
wprintf(L"Erasing the memory texture file data for %ls\n",
wName.c_str());
#endif
delete pData;
m_MEM_Files.erase(wName);
}
}
}
bool SkinManager::defaultCapeExists() {
std::wstring wTex = L"Special_Cape.png";
bool val = false;
{
std::lock_guard<std::mutex> lock(csMemFilesLock);
auto it = m_MEM_Files.find(wTex);
if (it != m_MEM_Files.end()) val = true;
}
return val;
}
bool SkinManager::isFileInMemoryTextures(const std::wstring& wName) {
bool val = false;
{
std::lock_guard<std::mutex> lock(csMemFilesLock);
auto it = m_MEM_Files.find(wName);
if (it != m_MEM_Files.end()) val = true;
}
return val;
}
void SkinManager::getMemFileDetails(const std::wstring& wName,
std::uint8_t** ppbData,
unsigned int* pByteCount) {
std::lock_guard<std::mutex> lock(csMemFilesLock);
auto it = m_MEM_Files.find(wName);
if (it != m_MEM_Files.end()) {
PMEMDATA pData = (*it).second;
*ppbData = pData->pbData;
*pByteCount = pData->byteCount;
}
}
void SkinManager::setAdditionalSkinBoxes(std::uint32_t dwSkinID,
SKIN_BOX* SkinBoxA,
unsigned int dwSkinBoxC) {
EntityRenderer* renderer =
EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model* pModel = renderer->getModel();
std::vector<ModelPart*>* pvModelPart = new std::vector<ModelPart*>;
std::vector<SKIN_BOX*>* pvSkinBoxes = new std::vector<SKIN_BOX*>;
{
std::lock_guard<std::mutex> lock_mp(csAdditionalModelParts);
std::lock_guard<std::mutex> lock_sb(csAdditionalSkinBoxes);
app.DebugPrintf(
"*** SetAdditionalSkinBoxes - Inserting model parts for skin %d "
"from "
"array of Skin Boxes\n",
dwSkinID & 0x0FFFFFFF);
for (unsigned int i = 0; i < dwSkinBoxC; i++) {
if (pModel) {
ModelPart* pModelPart = pModel->AddOrRetrievePart(&SkinBoxA[i]);
pvModelPart->push_back(pModelPart);
pvSkinBoxes->push_back(&SkinBoxA[i]);
}
}
m_AdditionalModelParts.insert(
std::pair<std::uint32_t, std::vector<ModelPart*>*>(dwSkinID,
pvModelPart));
m_AdditionalSkinBoxes.insert(
std::pair<std::uint32_t, std::vector<SKIN_BOX*>*>(dwSkinID,
pvSkinBoxes));
}
}
std::vector<ModelPart*>* SkinManager::setAdditionalSkinBoxes(
std::uint32_t dwSkinID, std::vector<SKIN_BOX*>* pvSkinBoxA) {
EntityRenderer* renderer =
EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model* pModel = renderer->getModel();
std::vector<ModelPart*>* pvModelPart = new std::vector<ModelPart*>;
{
std::lock_guard<std::mutex> lock_mp(csAdditionalModelParts);
std::lock_guard<std::mutex> lock_sb(csAdditionalSkinBoxes);
app.DebugPrintf(
"*** SetAdditionalSkinBoxes - Inserting model parts for skin %d "
"from "
"array of Skin Boxes\n",
dwSkinID & 0x0FFFFFFF);
for (auto it = pvSkinBoxA->begin(); it != pvSkinBoxA->end(); ++it) {
if (pModel) {
ModelPart* pModelPart = pModel->AddOrRetrievePart(*it);
pvModelPart->push_back(pModelPart);
}
}
m_AdditionalModelParts.insert(
std::pair<std::uint32_t, std::vector<ModelPart*>*>(dwSkinID,
pvModelPart));
m_AdditionalSkinBoxes.insert(
std::pair<std::uint32_t, std::vector<SKIN_BOX*>*>(dwSkinID,
pvSkinBoxA));
}
return pvModelPart;
}
std::vector<ModelPart*>* SkinManager::getAdditionalModelParts(
std::uint32_t dwSkinID) {
std::lock_guard<std::mutex> lock(csAdditionalModelParts);
std::vector<ModelPart*>* pvModelParts = nullptr;
if (m_AdditionalModelParts.size() > 0) {
auto it = m_AdditionalModelParts.find(dwSkinID);
if (it != m_AdditionalModelParts.end()) {
pvModelParts = (*it).second;
}
}
return pvModelParts;
}
std::vector<SKIN_BOX*>* SkinManager::getAdditionalSkinBoxes(
std::uint32_t dwSkinID) {
std::lock_guard<std::mutex> lock(csAdditionalSkinBoxes);
std::vector<SKIN_BOX*>* pvSkinBoxes = nullptr;
if (m_AdditionalSkinBoxes.size() > 0) {
auto it = m_AdditionalSkinBoxes.find(dwSkinID);
if (it != m_AdditionalSkinBoxes.end()) {
pvSkinBoxes = (*it).second;
}
}
return pvSkinBoxes;
}
unsigned int SkinManager::getAnimOverrideBitmask(std::uint32_t dwSkinID) {
std::lock_guard<std::mutex> lock(csAnimOverrideBitmask);
unsigned int uiAnimOverrideBitmask = 0L;
if (m_AnimOverrides.size() > 0) {
auto it = m_AnimOverrides.find(dwSkinID);
if (it != m_AnimOverrides.end()) {
uiAnimOverrideBitmask = (*it).second;
}
}
return uiAnimOverrideBitmask;
}
void SkinManager::setAnimOverrideBitmask(std::uint32_t dwSkinID,
unsigned int uiAnimOverrideBitmask) {
std::lock_guard<std::mutex> lock(csAnimOverrideBitmask);
if (m_AnimOverrides.size() > 0) {
auto it = m_AnimOverrides.find(dwSkinID);
if (it != m_AnimOverrides.end()) {
return; // already in here
}
}
m_AnimOverrides.insert(std::pair<std::uint32_t, unsigned int>(
dwSkinID, uiAnimOverrideBitmask));
}
std::uint32_t SkinManager::getSkinIdFromPath(const std::wstring& skin) {
bool dlcSkin = false;
unsigned int skinId = 0;
if (skin.size() >= 14) {
dlcSkin = skin.substr(0, 3).compare(L"dlc") == 0;
std::wstring skinValue = skin.substr(7, skin.size());
skinValue = skinValue.substr(0, skinValue.find_first_of(L'.'));
std::wstringstream ss;
if (dlcSkin)
ss << std::dec << skinValue.c_str();
else
ss << std::hex << skinValue.c_str();
ss >> skinId;
skinId = MAKE_SKIN_BITMASK(dlcSkin, skinId);
}
return skinId;
}
std::wstring SkinManager::getSkinPathFromId(std::uint32_t skinId) {
wchar_t chars[256];
if (GET_IS_DLC_SKIN_FROM_BITMASK(skinId)) {
swprintf(chars, 256, L"dlcskin%08d.png",
GET_DLC_SKIN_ID_FROM_BITMASK(skinId));
} else {
std::uint32_t ugcSkinIndex = GET_UGC_SKIN_ID_FROM_BITMASK(skinId);
std::uint32_t defaultSkinIndex =
GET_DEFAULT_SKIN_ID_FROM_BITMASK(skinId);
if (ugcSkinIndex == 0) {
swprintf(chars, 256, L"defskin%08X.png", defaultSkinIndex);
} else {
swprintf(chars, 256, L"ugcskin%08X.png", ugcSkinIndex);
}
}
return chars;
}

View file

@ -0,0 +1,108 @@
#pragma once
#include <cstdint>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
#include "app/common/App_structs.h"
#include "minecraft/world/entity/player/SkinBox.h"
#include "platform/XboxStubs.h"
class ModelPart;
class DLCManager;
class SkinManager {
public:
SkinManager();
// Skin get/set (require GameSettingsA pointer from Game)
void setPlayerSkin(int iPad, const std::wstring& name,
GAME_SETTINGS** gameSettingsA);
void setPlayerSkin(int iPad, std::uint32_t dwSkinId,
GAME_SETTINGS** gameSettingsA);
std::wstring getPlayerSkinName(int iPad, GAME_SETTINGS** gameSettingsA);
std::uint32_t getPlayerSkinId(int iPad, GAME_SETTINGS** gameSettingsA,
DLCManager& dlcManager);
// Cape get/set
void setPlayerCape(int iPad, const std::wstring& name,
GAME_SETTINGS** gameSettingsA);
void setPlayerCape(int iPad, std::uint32_t dwCapeId,
GAME_SETTINGS** gameSettingsA);
std::wstring getPlayerCapeName(int iPad, GAME_SETTINGS** gameSettingsA);
std::uint32_t getPlayerCapeId(int iPad, GAME_SETTINGS** gameSettingsA);
// Favorite skins
void setPlayerFavoriteSkin(int iPad, int iIndex, unsigned int uiSkinID,
GAME_SETTINGS** gameSettingsA);
unsigned int getPlayerFavoriteSkin(int iPad, int iIndex,
GAME_SETTINGS** gameSettingsA);
unsigned char getPlayerFavoriteSkinsPos(int iPad,
GAME_SETTINGS** gameSettingsA);
void setPlayerFavoriteSkinsPos(int iPad, int iPos,
GAME_SETTINGS** gameSettingsA);
unsigned int getPlayerFavoriteSkinsCount(int iPad,
GAME_SETTINGS** gameSettingsA);
void validateFavoriteSkins(int iPad, GAME_SETTINGS** gameSettingsA,
DLCManager& dlcManager);
// Additional model parts per player
std::uint32_t getAdditionalModelParts(int iPad);
// Additional model parts per skin texture
void setAdditionalSkinBoxes(std::uint32_t dwSkinID, SKIN_BOX* SkinBoxA,
unsigned int dwSkinBoxC);
std::vector<ModelPart*>* setAdditionalSkinBoxes(
std::uint32_t dwSkinID, std::vector<SKIN_BOX*>* pvSkinBoxA);
std::vector<ModelPart*>* getAdditionalModelParts(std::uint32_t dwSkinID);
std::vector<SKIN_BOX*>* getAdditionalSkinBoxes(std::uint32_t dwSkinID);
// Anim overrides
void setAnimOverrideBitmask(std::uint32_t dwSkinID,
unsigned int uiAnimOverrideBitmask);
unsigned int getAnimOverrideBitmask(std::uint32_t dwSkinID);
// Skin path <-> id conversion (static)
static std::uint32_t getSkinIdFromPath(const std::wstring& skin);
static std::wstring getSkinPathFromId(std::uint32_t skinId);
// Default cape
bool defaultCapeExists();
// Notch/Deadmau5 xuid checks
bool isXuidNotch(PlayerUID xuid);
bool isXuidDeadmau5(PlayerUID xuid);
// Memory texture files for player skins
void addMemoryTextureFile(const std::wstring& wName, std::uint8_t* pbData,
unsigned int byteCount);
void removeMemoryTextureFile(const std::wstring& wName);
void getMemFileDetails(const std::wstring& wName, std::uint8_t** ppbData,
unsigned int* pByteCount);
bool isFileInMemoryTextures(const std::wstring& wName);
// storing skin files
std::vector<std::wstring> vSkinNames;
// per-player additional model parts
std::uint32_t m_dwAdditionalModelParts[XUSER_MAX_COUNT];
private:
PlayerUID m_xuidNotch;
// Memory texture files
std::unordered_map<std::wstring, PMEMDATA> m_MEM_Files;
std::mutex csMemFilesLock;
// Additional model parts/skin boxes per skin id
std::unordered_map<std::uint32_t, std::vector<ModelPart*>*>
m_AdditionalModelParts;
std::unordered_map<std::uint32_t, std::vector<SKIN_BOX*>*>
m_AdditionalSkinBoxes;
std::unordered_map<std::uint32_t, unsigned int> m_AnimOverrides;
std::mutex csAdditionalModelParts;
std::mutex csAdditionalSkinBoxes;
std::mutex csAnimOverrideBitmask;
};

View file

@ -5,6 +5,4 @@
void Display::update() {}
int Game::GetTPConfigVal(wchar_t* pwchDataFile) { return 0; }
#endif