diff --git a/Minecraft.Client/Platform/Common/Consoles_App.cpp b/Minecraft.Client/Platform/Common/Consoles_App.cpp index f85d56632..5eb204c95 100644 --- a/Minecraft.Client/Platform/Common/Consoles_App.cpp +++ b/Minecraft.Client/Platform/Common/Consoles_App.cpp @@ -52,6 +52,10 @@ #include "../Minecraft.Client/Utils/ArchiveFile.h" #endif #include "../Minecraft.Client/Minecraft.h" +#if defined(__linux__) +#include +#include +#endif #ifdef _XBOX #include "../Minecraft.Client/Platform/Xbox/GameConfig/Minecraft.spa.h" #include "../Minecraft.Client/Platform/Xbox/Network/NetworkPlayerXbox.h" @@ -4600,7 +4604,33 @@ void CMinecraftApp::loadMediaArchive() { #endif if (!mediapath.empty()) { + // (check file.cpp) + // try to load the archive relative to the executable + // directory first. + // If that fails, fall back to the current working + // directory (original behavior) + // if everything fails, may god help you +#if defined(__linux__) + char exePathBuf[PATH_MAX]; + ssize_t exeLen = readlink("/proc/self/exe", exePathBuf, sizeof(exePathBuf) - 1); + if (exeLen != -1) { + exePathBuf[exeLen] = '\0'; + std::string exePathStr(exePathBuf); + size_t pos = exePathStr.find_last_of('/'); + std::string exeDir = (pos == std::string::npos) ? std::string(".") : exePathStr.substr(0, pos); + std::wstring exeDirW = convStringToWstring(exeDir.c_str()); + 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)); + } +#else m_mediaArchive = new ArchiveFile(File(mediapath)); +#endif } #if 0 std::string path = "Common\\media.arc"; diff --git a/Minecraft.World/IO/Files/File.cpp b/Minecraft.World/IO/Files/File.cpp index fb09c1a4f..e5bff5c98 100644 --- a/Minecraft.World/IO/Files/File.cpp +++ b/Minecraft.World/IO/Files/File.cpp @@ -69,6 +69,29 @@ File::File(const std::wstring& pathname) //: parent( NULL ) else m_abstractPathName = pathname; +#if defined(__linux__) + // If this is a relative path and it doesn't exist in the CWD, try to + // resolve it relative to the executable directory + if (!m_abstractPathName.empty() && m_abstractPathName[0] != L'/') { + const char* native = wstringtofilename(m_abstractPathName); + if (access(native, F_OK) == -1) { + char exePathBuf[PATH_MAX]; + ssize_t exeLen = readlink("/proc/self/exe", exePathBuf, sizeof(exePathBuf) - 1); + if (exeLen != -1) { + exePathBuf[exeLen] = '\0'; + std::string exePathStr(exePathBuf); + size_t pos = exePathStr.find_last_of('/'); + std::string exeDir = (pos == std::string::npos) ? std::string(".") : exePathStr.substr(0, pos); + std::wstring exeDirW = convStringToWstring(exeDir); + std::wstring candidate = exeDirW + pathSeparator + m_abstractPathName; + const char* candNative = wstringtofilename(candidate); + if (access(candNative, F_OK) != -1) { + m_abstractPathName = candidate; + } + } + } + } +#endif #ifdef _WINDOWS64 std::string path = wstringtofilename(m_abstractPathName); std::string finalPath = StorageManager.GetMountedPath(path.c_str());