|  | @@ -79,6 +79,7 @@ void IVCMIDirs::init()
 | 
	
		
			
				|  |  |  class VCMIDirsWIN32 final : public IVCMIDirs
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	public:
 | 
	
		
			
				|  |  | +		VCMIDirsWIN32();
 | 
	
		
			
				|  |  |  		bfs::path userDataPath() const override;
 | 
	
		
			
				|  |  |  		bfs::path userCachePath() const override;
 | 
	
		
			
				|  |  |  		bfs::path userConfigPath() const override;
 | 
	
	
		
			
				|  | @@ -97,62 +98,53 @@ class VCMIDirsWIN32 final : public IVCMIDirs
 | 
	
		
			
				|  |  |  		std::string libraryName(const std::string& basename) const override;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	protected:
 | 
	
		
			
				|  |  | -		mutable std::optional<JsonNode> dirsConfig;
 | 
	
		
			
				|  |  | -		void loadDirsJsonIfNeeded() const;
 | 
	
		
			
				|  |  | +		std::unique_ptr<JsonNode> dirsConfig;
 | 
	
		
			
				|  |  |  		bfs::path getPathFromConfigOrDefault(const std::string& key, const std::function<bfs::path()>& fallbackFunc) const;
 | 
	
		
			
				|  |  |  		std::wstring utf8ToWstring(const std::string& str) const;
 | 
	
		
			
				|  |  | +		std::string pathToUtf8(const bfs::path& path) const;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -std::wstring VCMIDirsWIN32::utf8ToWstring(const std::string& str) const
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -	std::wstring result;
 | 
	
		
			
				|  |  | -	int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
 | 
	
		
			
				|  |  | -	if (size_needed > 0)
 | 
	
		
			
				|  |  | -	{
 | 
	
		
			
				|  |  | -		result.resize(size_needed - 1);
 | 
	
		
			
				|  |  | -		MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, result.data(), size_needed);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return result;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static std::string pathToUtf8(const bfs::path& path)
 | 
	
		
			
				|  |  | +VCMIDirsWIN32::VCMIDirsWIN32()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	std::wstring wstr = path.wstring();
 | 
	
		
			
				|  |  | -	int size = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
 | 
	
		
			
				|  |  | -	std::string result(size - 1, 0);
 | 
	
		
			
				|  |  | -	WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, result.data(), size, nullptr, nullptr);
 | 
	
		
			
				|  |  | -	return result;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void VCMIDirsWIN32::loadDirsJsonIfNeeded() const
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -	if (dirsConfig.has_value())
 | 
	
		
			
				|  |  | -		return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	wchar_t currentPath[MAX_PATH];
 | 
	
		
			
				|  |  |  	GetModuleFileNameW(nullptr, currentPath, MAX_PATH);
 | 
	
		
			
				|  |  |  	auto configPath = bfs::path(currentPath).parent_path() / "config" / "dirs.json";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (!bfs::exists(configPath))
 | 
	
		
			
				|  |  | -	{
 | 
	
		
			
				|  |  | -		dirsConfig = std::nullopt;
 | 
	
		
			
				|  |  |  		return;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	std::ifstream in(pathToUtf8(configPath), std::ios::binary);
 | 
	
		
			
				|  |  |  	if (!in)
 | 
	
		
			
				|  |  | -	{
 | 
	
		
			
				|  |  | -		dirsConfig = std::nullopt;
 | 
	
		
			
				|  |  |  		return;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	std::string buffer((std::istreambuf_iterator<char>(in)), {});
 | 
	
		
			
				|  |  | -	dirsConfig = JsonNode(reinterpret_cast<const std::byte*>(buffer.data()), buffer.size(), pathToUtf8(configPath));
 | 
	
		
			
				|  |  | +	dirsConfig = std::make_unique<JsonNode>(reinterpret_cast<const std::byte*>(buffer.data()), buffer.size(), pathToUtf8(configPath));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +std::string VCMIDirsWIN32::pathToUtf8(const bfs::path& path) const
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	std::wstring wstr = path.wstring();
 | 
	
		
			
				|  |  | +	int size = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
 | 
	
		
			
				|  |  | +	std::string result(size - 1, 0);
 | 
	
		
			
				|  |  | +	WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, result.data(), size, nullptr, nullptr);
 | 
	
		
			
				|  |  | +	return result;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +std::wstring VCMIDirsWIN32::utf8ToWstring(const std::string& str) const
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	std::wstring result;
 | 
	
		
			
				|  |  | +	int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
 | 
	
		
			
				|  |  | +	if (size_needed > 0)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		result.resize(size_needed - 1);
 | 
	
		
			
				|  |  | +		MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, result.data(), size_needed);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return result;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bfs::path VCMIDirsWIN32::getPathFromConfigOrDefault(const std::string& key, const std::function<bfs::path()>& fallbackFunc) const
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	loadDirsJsonIfNeeded();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (!dirsConfig || !dirsConfig->isStruct())
 | 
	
		
			
				|  |  |  		return fallbackFunc();
 |